1 /* 2 * saveas.c 3 * Copyright (C) 1998-2001 A.J. van Os; Released under GPL 4 * 5 * Description: 6 * Functions to save the results as a textfile or a drawfile 7 */ 8 9 #include <stdio.h> 10 #include <string.h> 11 #include "DeskLib:Menu.h" 12 #include "DeskLib:Save.h" 13 #include "DeskLib:Template.h" 14 #include "DeskLib:Window.h" 15 #include "drawfile.h" 16 #include "antiword.h" 17 18 /* The window handle of the save window */ 19 static window_handle tSaveWindow = 0; 20 21 /* Xfer_send box fields */ 22 #define DRAG_SPRITE 3 23 #define OK_BUTTON 0 24 #define CANCEL_BUTTON (-1) 25 #define FILENAME_ICON 2 26 27 28 /* 29 * saveas - a wrapper around Save_InitSaveWindowhandler 30 */ 31 static void 32 saveas(int iFileType, char *szOutfile, size_t tEstSize, 33 save_filesaver save_function, void *pvReference) 34 { 35 TRACE_MSG("saveas"); 36 37 if (tSaveWindow == 0) { 38 tSaveWindow = Window_Create("xfer_send", template_TITLEMIN); 39 } 40 Icon_SetText(tSaveWindow, FILENAME_ICON, szOutfile); 41 Window_Show(tSaveWindow, open_UNDERPOINTER); 42 (void)Save_InitSaveWindowHandler(tSaveWindow, FALSE, TRUE, TRUE, 43 DRAG_SPRITE, OK_BUTTON, CANCEL_BUTTON, FILENAME_ICON, 44 save_function, NULL, NULL, tEstSize, iFileType, pvReference); 45 } /* end of saveas */ 46 47 static BOOL 48 bWrite2File(void *pvBytes, size_t tSize, FILE *pFile, const char *szFilename) 49 { 50 if (fwrite(pvBytes, sizeof(char), tSize, pFile) != tSize) { 51 werr(0, "I can't write to '%s'", szFilename); 52 return FALSE; 53 } 54 return TRUE; 55 } /* end of bWrite2File */ 56 57 /* 58 * bText2File - Save the generated draw file to a Text file 59 */ 60 static BOOL 61 bText2File(char *szFilename, void *pvHandle) 62 { 63 FILE *pFile; 64 diagram_type *pDiag; 65 drawfile_object *pObj; 66 drawfile_text *pText; 67 const char *pcTmp; 68 int iToGo, iX, iYtopPrev, iHeight, iLines; 69 BOOL bFirst, bIndent, bSuccess; 70 71 TRACE_MSG("bText2File"); 72 73 fail(szFilename == NULL || szFilename[0] == '\0'); 74 fail(pvHandle == NULL); 75 76 DBG_MSG(szFilename); 77 78 pDiag = (diagram_type *)pvHandle; 79 pFile = fopen(szFilename, "w"); 80 if (pFile == NULL) { 81 werr(0, "I can't open '%s' for writing", szFilename); 82 return FALSE; 83 } 84 bFirst = TRUE; 85 iYtopPrev = 0; 86 iHeight = (int)lWord2DrawUnits20(DEFAULT_FONT_SIZE); 87 bSuccess = TRUE; 88 fail(pDiag->tInfo.length < offsetof(drawfile_diagram, objects)); 89 iToGo = pDiag->tInfo.length - offsetof(drawfile_diagram, objects); 90 DBG_DEC(iToGo); 91 pcTmp = (const char *)pDiag->tInfo.data + 92 offsetof(drawfile_diagram, objects); 93 while (iToGo > 0 && bSuccess) { 94 pObj = (drawfile_object *)pcTmp; 95 switch (pObj->type) { 96 case drawfile_TYPE_TEXT: 97 pText = &pObj->data.text; 98 /* Compute the number of lines */ 99 iLines = (iYtopPrev - pText->bbox.max.y + 100 iHeight / 2) / iHeight; 101 DBG_DEC_C(iLines < 0, iYtopPrev); 102 DBG_DEC_C(iLines < 0, pText->bbox.max.y); 103 fail(iLines < 0); 104 bIndent = iLines > 0 || bFirst; 105 bFirst = FALSE; 106 /* Print the newlines */ 107 while (iLines > 0 && bSuccess) { 108 bSuccess = bWrite2File("\n", 109 1, pFile, szFilename); 110 iLines--; 111 } 112 /* Print the indentation */ 113 if (bIndent && bSuccess) { 114 for (iX = Drawfile_ScreenToDraw(8); 115 iX <= pText->bbox.min.x && bSuccess; 116 iX += Drawfile_ScreenToDraw(16)) { 117 bSuccess = bWrite2File(" ", 118 1, pFile, szFilename); 119 } 120 } 121 if (!bSuccess) { 122 break; 123 } 124 /* Print the text object */ 125 bSuccess = bWrite2File(pText->text, 126 strlen(pText->text), pFile, szFilename); 127 /* Setup for the next object */ 128 iYtopPrev = pText->bbox.max.y; 129 iHeight = pText->bbox.max.y - pText->bbox.min.y; 130 break; 131 case drawfile_TYPE_FONT_TABLE: 132 case drawfile_TYPE_PATH: 133 case drawfile_TYPE_SPRITE: 134 case drawfile_TYPE_JPEG: 135 /* These are not relevant in a textfile */ 136 break; 137 default: 138 DBG_DEC(pObj->type); 139 bSuccess = FALSE; 140 break; 141 } 142 pcTmp += pObj->size; 143 iToGo -= pObj->size; 144 } 145 DBG_DEC_C(iToGo != 0, iToGo); 146 if (bSuccess) { 147 bSuccess = bWrite2File("\n", 1, pFile, szFilename); 148 } 149 (void)fclose(pFile); 150 if (bSuccess) { 151 vSetFiletype(szFilename, FILETYPE_TEXT); 152 } else { 153 (void)remove(szFilename); 154 werr(0, "Unable to save textfile '%s'", szFilename); 155 } 156 return bSuccess; 157 } /* end of bText2File */ 158 159 /* 160 * bSaveTextfile - save the diagram as a text file 161 */ 162 BOOL 163 bSaveTextfile(event_pollblock *pEvent, void *pvReference) 164 { 165 diagram_type *pDiag; 166 size_t tRecLen, tNbrRecs, tEstSize; 167 168 TRACE_MSG("bSaveTextfile"); 169 170 fail(pEvent == NULL); 171 fail(pvReference == NULL); 172 173 pDiag = (diagram_type *)pvReference; 174 175 switch (pEvent->type) { 176 case event_SEND: /* From a menu */ 177 fail(pEvent->data.message.header.action != message_MENUWARN); 178 if (menu_currentopen != pDiag->pSaveMenu || 179 pEvent->data.message.data.menuwarn.selection[0] != 180 SAVEMENU_SAVETEXT) { 181 return FALSE; 182 } 183 break; 184 case event_KEY: /* From a key short cut */ 185 if (pEvent->data.key.caret.window != pDiag->tMainWindow) { 186 return FALSE; 187 } 188 break; 189 default: 190 DBG_DEC(pEvent->type); 191 return FALSE; 192 } 193 194 tRecLen = sizeof(drawfile_text) + DEFAULT_SCREEN_WIDTH * 2 / 3; 195 tNbrRecs = pDiag->tInfo.length / tRecLen + 1; 196 tEstSize = tNbrRecs * DEFAULT_SCREEN_WIDTH * 2 / 3; 197 DBG_DEC(tEstSize); 198 199 saveas(FILETYPE_TEXT, "WordText", tEstSize, bText2File, pDiag); 200 return TRUE; 201 } /* end of bSaveTextfile */ 202 203 /* 204 * bDraw2File - Save the generated draw file to a Draw file 205 * 206 * Remark: This is not a simple copy action. The origin of the 207 * coordinates (0,0) must move from the top-left corner to the 208 * bottom-left corner. 209 */ 210 static BOOL 211 bDraw2File(char *szFilename, void *pvHandle) 212 { 213 FILE *pFile; 214 diagram_type *pDiagram; 215 wimp_box *pBbox; 216 drawfile_object *pObj; 217 drawfile_text *pText; 218 drawfile_path *pPath; 219 drawfile_sprite *pSprite; 220 drawfile_jpeg *pJpeg; 221 int *piPath; 222 char *pcTmp; 223 int iYadd, iToGo, iSize; 224 BOOL bSuccess; 225 226 TRACE_MSG("bDraw2File"); 227 228 fail(szFilename == NULL || szFilename[0] == '\0'); 229 fail(pvHandle == NULL); 230 231 NO_DBG_MSG(szFilename); 232 233 pDiagram = (diagram_type *)pvHandle; 234 pFile = fopen(szFilename, "wb"); 235 if (pFile == NULL) { 236 werr(0, "I can't open '%s' for writing", szFilename); 237 return FALSE; 238 } 239 iToGo = pDiagram->tInfo.length; 240 DBG_DEC(iToGo); 241 pcTmp = pDiagram->tInfo.data; 242 bSuccess = bWrite2File(pcTmp, 243 offsetof(drawfile_diagram, bbox), pFile, szFilename); 244 if (bSuccess) { 245 pcTmp += offsetof(drawfile_diagram, bbox); 246 iToGo -= offsetof(drawfile_diagram, bbox); 247 pBbox = (wimp_box *)pcTmp; 248 iYadd = -pBbox->min.y; 249 pBbox->min.y += iYadd; 250 pBbox->max.y += iYadd; 251 bSuccess = bWrite2File(pcTmp, 252 sizeof(*pBbox), pFile, szFilename); 253 iToGo -= sizeof(*pBbox); 254 DBG_DEC(iToGo); 255 pcTmp += sizeof(*pBbox); 256 } else { 257 iYadd = 0; 258 } 259 while (iToGo > 0 && bSuccess) { 260 pObj = (drawfile_object *)pcTmp; 261 iSize = pObj->size; 262 switch (pObj->type) { 263 case drawfile_TYPE_FONT_TABLE: 264 bSuccess = bWrite2File(pcTmp, 265 iSize, pFile, szFilename); 266 pcTmp += iSize; 267 iToGo -= iSize; 268 break; 269 case drawfile_TYPE_TEXT: 270 pText = &pObj->data.text; 271 /* First correct the coordinates */ 272 pText->bbox.min.y += iYadd; 273 pText->bbox.max.y += iYadd; 274 pText->base.y += iYadd; 275 /* Now write the information to file */ 276 bSuccess = bWrite2File(pcTmp, 277 iSize, pFile, szFilename); 278 pcTmp += pObj->size; 279 iToGo -= pObj->size; 280 break; 281 case drawfile_TYPE_PATH: 282 pPath = &pObj->data.path; 283 /* First correct the coordinates */ 284 pPath->bbox.min.y += iYadd; 285 pPath->bbox.max.y += iYadd; 286 /* Now write the information to file */ 287 bSuccess = bWrite2File(pPath, 288 sizeof(*pPath), pFile, szFilename); 289 pcTmp += sizeof(*pPath); 290 iSize = pObj->size - sizeof(*pPath); 291 fail(iSize < 14 * sizeof(int)); 292 /* Second correct the path coordinates */ 293 piPath = xmalloc(iSize); 294 memcpy(piPath, pcTmp, iSize); 295 piPath[ 2] += iYadd; 296 piPath[ 5] += iYadd; 297 piPath[ 8] += iYadd; 298 piPath[11] += iYadd; 299 if (bSuccess) { 300 bSuccess = bWrite2File(piPath, 301 iSize, pFile, szFilename); 302 pcTmp += iSize; 303 } 304 piPath = xfree(piPath); 305 iToGo -= pObj->size; 306 break; 307 case drawfile_TYPE_SPRITE: 308 pSprite = &pObj->data.sprite; 309 /* First correct the coordinates */ 310 pSprite->bbox.min.y += iYadd; 311 pSprite->bbox.max.y += iYadd; 312 /* Now write the information to file */ 313 bSuccess = bWrite2File(pcTmp, 314 iSize, pFile, szFilename); 315 pcTmp += pObj->size; 316 iToGo -= pObj->size; 317 break; 318 case drawfile_TYPE_JPEG: 319 pJpeg = &pObj->data.jpeg; 320 /* First correct the coordinates */ 321 pJpeg->bbox.min.y += iYadd; 322 pJpeg->bbox.max.y += iYadd; 323 pJpeg->trfm.entries[2][1] += iYadd; 324 /* Now write the information to file */ 325 bSuccess = bWrite2File(pcTmp, 326 iSize, pFile, szFilename); 327 pcTmp += pObj->size; 328 iToGo -= pObj->size; 329 break; 330 default: 331 DBG_DEC(pObj->type); 332 bSuccess = FALSE; 333 break; 334 } 335 } 336 DBG_DEC_C(iToGo != 0, iToGo); 337 (void)fclose(pFile); 338 if (bSuccess) { 339 vSetFiletype(szFilename, FILETYPE_DRAW); 340 } else { 341 (void)remove(szFilename); 342 werr(0, "Unable to save drawfile '%s'", szFilename); 343 } 344 return bSuccess; 345 } /* end of bDraw2File */ 346 347 /* 348 * bSaveDrawfile - save the diagram as a draw file 349 */ 350 BOOL 351 bSaveDrawfile(event_pollblock *pEvent, void *pvReference) 352 { 353 diagram_type *pDiag; 354 size_t tEstSize; 355 356 TRACE_MSG("bSaveDrawfile"); 357 358 fail(pEvent == NULL); 359 fail(pvReference == NULL); 360 361 pDiag = (diagram_type *)pvReference; 362 363 switch (pEvent->type) { 364 case event_SEND: /* From a menu */ 365 fail(pEvent->data.message.header.action != message_MENUWARN); 366 if (menu_currentopen != pDiag->pSaveMenu || 367 pEvent->data.message.data.menuwarn.selection[0] != 368 SAVEMENU_SAVEDRAW) { 369 return FALSE; 370 } 371 break; 372 case event_KEY: /* From a key short cut */ 373 if (pEvent->data.key.caret.window != pDiag->tMainWindow) { 374 return FALSE; 375 } 376 break; 377 default: 378 DBG_DEC(pEvent->type); 379 return FALSE; 380 } 381 382 tEstSize = pDiag->tInfo.length; 383 DBG_DEC(tEstSize); 384 385 saveas(FILETYPE_DRAW, "WordDraw", tEstSize, bDraw2File, pDiag); 386 return TRUE; 387 } /* end of bSaveDrawfile */ 388