Imported from antiword-0.37.tar.gz.
[antiword.git] / draw.c
blobf833d75ea97ae86ce4040e3282e177102ff68a0e
1 /*
2 * draw.c
3 * Copyright (C) 1998-2005 A.J. van Os; Released under GPL
5 * Description:
6 * Functions to deal with the Draw format
7 */
9 #include <stdlib.h>
10 #include <ctype.h>
11 #include <string.h>
12 #include "DeskLib:KeyCodes.h"
13 #include "DeskLib:Error.h"
14 #include "DeskLib:Menu.h"
15 #include "DeskLib:Template.h"
16 #include "DeskLib:Window.h"
17 #include "DeskLib:EventMsg.h"
18 #include "flexlib:flex.h"
19 #include "drawfile.h"
20 #include "antiword.h"
22 /* The work area must be a little bit larger than the diagram */
23 #define WORKAREA_EXTENSION 5
24 /* Diagram memory */
25 #define INITIAL_SIZE 32768 /* 32k */
26 #define EXTENSION_SIZE 4096 /* 4k */
27 /* Main window title */
28 #define WINDOW_TITLE_LEN 28
29 #define FILENAME_TITLE_LEN (WINDOW_TITLE_LEN - 10)
32 #if !defined(__GNUC__)
33 int
34 flex_alloc(flex_ptr anchor, int n)
36 void *pvTmp;
38 TRACE_MSG("flex_alloc");
40 if (anchor == NULL || n < 0) {
41 return 0;
43 if (n == 0) {
44 n = 1;
46 pvTmp = malloc(n);
47 if (pvTmp == NULL) {
48 return 0;
50 *anchor = pvTmp;
51 return 1;
52 } /* end of flex_alloc */
54 void
55 flex_free(flex_ptr anchor)
57 TRACE_MSG("flex_free");
59 if (anchor == NULL || *anchor == NULL) {
60 return;
62 free(*anchor);
63 *anchor = NULL;
64 } /* end of flex_free */
66 int
67 flex_extend(flex_ptr anchor, int newsize)
69 void *pvTmp;
71 TRACE_MSG("flex_extend");
73 if (anchor == NULL || newsize < 0) {
74 return 0;
76 if (newsize == 0) {
77 newsize = 1;
79 pvTmp = realloc(*anchor, newsize);
80 if (pvTmp == NULL) {
81 return 0;
83 *anchor = pvTmp;
84 return 1;
85 } /* end of flex_extend */
86 #endif /* !__GNUC__ */
89 * vCreateMainWindow - create the Main window
91 * remark: does not return if the Main window can't be created
93 static window_handle
94 tCreateMainWindow(void)
96 window_handle tMainWindow;
98 TRACE_MSG("tCreateMainWindow");
100 tMainWindow = Window_Create("MainWindow", template_TITLEMIN);
101 if (tMainWindow == 0) {
102 werr(1, "I can't find the 'MainWindow' template");
104 return tMainWindow;
105 } /* end of tCreateMainWindow */
108 * vCreateScaleWindow - create the Scale view window
110 * remark: does not return if the Scale view window can't be created
112 static window_handle
113 tCreateScaleWindow(void)
115 window_handle tScaleWindow;
117 TRACE_MSG("tCreateScaleWindow");
119 tScaleWindow = Window_Create("ScaleView", template_TITLEMIN);
120 if (tScaleWindow == 0) {
121 werr(1, "I can't find the 'ScaleView' template");
123 return tScaleWindow;
124 } /* end of tCreateScaleWindow */
127 * pCreateDiagram - create and initialize a diagram
129 * remark: does not return if the diagram can't be created
131 diagram_type *
132 pCreateDiagram(const char *szTask, const char *szFilename)
134 diagram_type *pDiag;
135 options_type tOptions;
136 window_handle tMainWindow, tScaleWindow;
137 wimp_box tBox;
139 TRACE_MSG("pCreateDiagram");
141 fail(szTask == NULL || szTask[0] == '\0');
143 /* Create the main window */
144 tMainWindow = tCreateMainWindow();
146 /* Create the scale view window */
147 tScaleWindow = tCreateScaleWindow();
149 /* Get the necessary memory */
150 pDiag = xmalloc(sizeof(diagram_type));
151 if (flex_alloc((flex_ptr)&pDiag->tInfo.data, INITIAL_SIZE) != 1) {
152 werr(1, "Memory allocation failed, unable to continue");
155 /* Initialize the diagram */
156 vGetOptions(&tOptions);
157 pDiag->tMainWindow = tMainWindow;
158 pDiag->tScaleWindow = tScaleWindow;
159 pDiag->iScaleFactorCurr = tOptions.iScaleFactor;
160 pDiag->iScaleFactorTemp = tOptions.iScaleFactor;
161 pDiag->tMemorySize = INITIAL_SIZE;
162 tBox.min.x = 0;
163 tBox.min.y = -(Drawfile_ScreenToDraw(32 + 3) * 8 + 1);
164 tBox.max.x = Drawfile_ScreenToDraw(16) * MIN_SCREEN_WIDTH + 1;
165 tBox.max.y = 0;
166 Error_CheckFatal(Drawfile_CreateDiagram(&pDiag->tInfo,
167 pDiag->tMemorySize, szTask, tBox));
168 DBG_DEC(pDiag->tInfo.length);
169 pDiag->lXleft = 0;
170 pDiag->lYtop = 0;
171 strncpy(pDiag->szFilename,
172 szBasename(szFilename), sizeof(pDiag->szFilename) - 1);
173 pDiag->szFilename[sizeof(pDiag->szFilename) - 1] = '\0';
174 /* Return success */
175 return pDiag;
176 } /* end of pCreateDiagram */
179 * bDestroyDiagram - remove a diagram by freeing the memory it uses
181 BOOL
182 bDestroyDiagram(event_pollblock *pEvent, void *pvReference)
184 diagram_type *pDiag;
185 window_handle tWindow;
187 TRACE_MSG("bDestroyDiagram");
189 fail(pEvent == NULL);
190 fail(pvReference == NULL);
192 if (pEvent == NULL || pvReference == NULL) {
193 return FALSE;
196 pDiag = (diagram_type *)pvReference;
198 switch (pEvent->type) {
199 case event_CLOSE:
200 tWindow = pEvent->data.openblock.window;
201 break;
202 case event_KEY:
203 tWindow = pEvent->data.key.caret.window;
204 break;
205 default:
206 DBG_DEC(pEvent->type);
207 return FALSE;
209 if (tWindow != pDiag->tMainWindow) {
210 return FALSE;
213 /* Delete the main window */
214 Window_Delete(pDiag->tMainWindow);
215 pDiag->tMainWindow = 0;
217 /* Delete the scale window */
218 Window_Delete(pDiag->tScaleWindow);
219 pDiag->tScaleWindow = 0;
221 #if defined(__GNUC__)
223 * Remove all references to the diagram that will be free-ed
224 * by undoing the EventMsg_Claim's from within the Menu_Warn's
226 while (EventMsg_ReleaseSpecific(message_MENUWARNING, window_ANY,
227 bSaveTextfile, pDiag))
228 ; /* EMPTY */
229 while (EventMsg_ReleaseSpecific(message_MENUWARNING, window_ANY,
230 bSaveDrawfile, pDiag))
231 ; /* EMPTY */
232 while (EventMsg_ReleaseSpecific(message_MENUWARNING, window_ANY,
233 bScaleOpenAction, pDiag))
234 ; /* EMPTY */
235 #endif /* __GNUC__ */
237 /* Free the memory */
238 if (pDiag->tInfo.data != NULL && pDiag->tMemorySize != 0) {
239 flex_free((flex_ptr)&pDiag->tInfo.data);
241 /* Just to be on the save side */
242 pDiag->tInfo.data = NULL;
243 pDiag->tInfo.length = 0;
244 pDiag->tMemorySize = 0;
246 /* Destroy the diagram itself */
247 pDiag = xfree(pDiag);
248 return TRUE;
249 } /* end of bDestroyDiagram */
252 * vExtendDiagramSize - make sure the diagram is big enough
254 static void
255 vExtendDiagramSize(diagram_type *pDiag, size_t tSize)
257 TRACE_MSG("vExtendDiagramSize");
259 fail(pDiag == NULL || tSize % 4 != 0);
261 while (pDiag->tInfo.length + tSize > pDiag->tMemorySize) {
262 if (flex_extend((flex_ptr)&pDiag->tInfo.data,
263 pDiag->tMemorySize + EXTENSION_SIZE) != 1) {
264 werr(1, "Memory extend failed, unable to continue");
266 pDiag->tMemorySize += EXTENSION_SIZE;
267 NO_DBG_DEC(pDiag->tMemorySize);
269 TRACE_MSG("end of vExtendDiagramSize");
270 } /* end of vExtendDiagramSize */
273 * vPrologue2 - prologue part 2; add a font list to a diagram
275 void
276 vPrologue2(diagram_type *pDiag, int iWordVersion)
278 drawfile_object *pNew;
279 const font_table_type *pTmp;
280 char *pcTmp;
281 size_t tRealSize, tSize;
282 int iCount;
284 TRACE_MSG("vPrologue2");
286 fail(pDiag == NULL);
288 if (tGetFontTableLength() == 0) {
289 return;
291 tRealSize = offsetof(drawfile_object, data);
292 pTmp = NULL;
293 while ((pTmp = pGetNextFontTableRecord(pTmp)) != NULL) {
294 tRealSize += 2 + strlen(pTmp->szOurFontname);
296 DBG_DEC(tRealSize);
297 tSize = ROUND4(tRealSize);
298 vExtendDiagramSize(pDiag, tSize);
299 pNew = xmalloc(tSize);
300 memset(pNew, 0, tSize);
301 pNew->type = drawfile_TYPE_FONT_TABLE;
302 pNew->size = tSize;
303 pcTmp = (char *)&pNew->data.font_table.font_def[0].font_ref;
304 iCount = 0;
305 pTmp = NULL;
306 while ((pTmp = pGetNextFontTableRecord(pTmp)) != NULL) {
307 *pcTmp = ++iCount;
308 pcTmp++;
309 strcpy(pcTmp, pTmp->szOurFontname);
310 pcTmp += 1 + strlen(pTmp->szOurFontname);
312 Error_CheckFatal(Drawfile_AppendObject(&pDiag->tInfo,
313 pDiag->tMemorySize, pNew, TRUE));
314 pNew = xfree(pNew);
315 } /* end of vPrologue2 */
318 * vSubstring2Diagram - put a sub string into a diagram
320 void
321 vSubstring2Diagram(diagram_type *pDiag,
322 char *szString, size_t tStringLength, long lStringWidth,
323 UCHAR ucFontColor, USHORT usFontstyle, drawfile_fontref tFontRef,
324 USHORT usFontSize, USHORT usMaxFontSize)
326 drawfile_object *pNew;
327 long lSizeX, lSizeY, lOffset, l20, lYMove;
328 size_t tRealSize, tSize;
330 TRACE_MSG("vSubstring2Diagram");
332 fail(pDiag == NULL || szString == NULL);
333 fail(pDiag->lXleft < 0);
334 fail(tStringLength != strlen(szString));
335 fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
336 fail(usMaxFontSize < MIN_FONT_SIZE || usMaxFontSize > MAX_FONT_SIZE);
337 fail(usFontSize > usMaxFontSize);
339 if (szString[0] == '\0' || tStringLength == 0) {
340 return;
343 if (tFontRef == 0) {
344 lOffset = Drawfile_ScreenToDraw(2);
345 l20 = Drawfile_ScreenToDraw(32 + 3);
346 lSizeX = Drawfile_ScreenToDraw(16);
347 lSizeY = Drawfile_ScreenToDraw(32);
348 } else {
349 lOffset = lToBaseLine(usMaxFontSize);
350 l20 = lWord2DrawUnits20(usMaxFontSize);
351 lSizeX = lWord2DrawUnits00(usFontSize);
352 lSizeY = lWord2DrawUnits00(usFontSize);
355 lYMove = 0;
357 /* Up for superscript */
358 if (bIsSuperscript(usFontstyle)) {
359 lYMove = lMilliPoints2DrawUnits((((long)usFontSize + 1) / 2) * 375);
361 /* Down for subscript */
362 if (bIsSubscript(usFontstyle)) {
363 lYMove = -lMilliPoints2DrawUnits((long)usFontSize * 125);
366 tRealSize = offsetof(drawfile_object, data);
367 tRealSize += sizeof(drawfile_text) + tStringLength;
368 tSize = ROUND4(tRealSize);
369 vExtendDiagramSize(pDiag, tSize);
370 pNew = xmalloc(tSize);
371 memset(pNew, 0, tSize);
372 pNew->type = drawfile_TYPE_TEXT;
373 pNew->size = tSize;
374 pNew->data.text.bbox.min.x = (int)pDiag->lXleft;
375 pNew->data.text.bbox.min.y = (int)(pDiag->lYtop + lYMove);
376 pNew->data.text.bbox.max.x = (int)(pDiag->lXleft + lStringWidth);
377 pNew->data.text.bbox.max.y = (int)(pDiag->lYtop + l20 + lYMove);
378 pNew->data.text.fill.value = (int)ulColor2Color(ucFontColor);
379 pNew->data.text.bg_hint.value = 0xffffff00; /* White */
380 pNew->data.text.style.font_ref = tFontRef;
381 pNew->data.text.style.reserved[0] = 0;
382 pNew->data.text.style.reserved[1] = 0;
383 pNew->data.text.style.reserved[2] = 0;
384 pNew->data.text.xsize = (int)lSizeX;
385 pNew->data.text.ysize = (int)lSizeY;
386 pNew->data.text.base.x = (int)pDiag->lXleft;
387 pNew->data.text.base.y = (int)(pDiag->lYtop + lOffset + lYMove);
388 strncpy(pNew->data.text.text, szString, tStringLength);
389 pNew->data.text.text[tStringLength] = '\0';
390 Error_CheckFatal(Drawfile_AppendObject(&pDiag->tInfo,
391 pDiag->tMemorySize, pNew, TRUE));
392 pNew = xfree(pNew);
393 /*draw_translateText(&pDiag->tInfo);*/
394 pDiag->lXleft += lStringWidth;
395 TRACE_MSG("leaving vSubstring2Diagram");
396 } /* end of vSubstring2Diagram */
399 * vImage2Diagram - put an image into a diagram
401 void
402 vImage2Diagram(diagram_type *pDiag, const imagedata_type *pImg,
403 UCHAR *pucImage, size_t tImageSize)
405 drawfile_object *pNew;
406 long lWidth, lHeight;
407 size_t tRealSize, tSize;
409 TRACE_MSG("vImage2Diagram");
411 fail(pDiag == NULL);
412 fail(pImg == NULL);
413 fail(pDiag->lXleft < 0);
414 fail(pImg->eImageType != imagetype_is_dib &&
415 pImg->eImageType != imagetype_is_jpeg);
417 DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
419 lWidth = lPoints2DrawUnits(pImg->iHorSizeScaled);
420 lHeight = lPoints2DrawUnits(pImg->iVerSizeScaled);
421 DBG_DEC(lWidth);
422 DBG_DEC(lHeight);
424 pDiag->lYtop -= lHeight;
426 tRealSize = offsetof(drawfile_object, data);
427 switch (pImg->eImageType) {
428 case imagetype_is_dib:
429 tRealSize += sizeof(drawfile_sprite) + tImageSize;
430 tSize = ROUND4(tRealSize);
431 vExtendDiagramSize(pDiag, tSize);
432 pNew = xmalloc(tSize);
433 memset(pNew, 0, tSize);
434 pNew->type = drawfile_TYPE_SPRITE;
435 pNew->size = tSize;
436 pNew->data.sprite.bbox.min.x = (int)pDiag->lXleft;
437 pNew->data.sprite.bbox.min.y = (int)pDiag->lYtop;
438 pNew->data.sprite.bbox.max.x = (int)(pDiag->lXleft + lWidth);
439 pNew->data.sprite.bbox.max.y = (int)(pDiag->lYtop + lHeight);
440 memcpy(&pNew->data.sprite.header, pucImage, tImageSize);
441 break;
442 case imagetype_is_jpeg:
443 #if defined(DEBUG)
444 (void)bGetJpegInfo(pucImage, tImageSize);
445 #endif /* DEBUG */
446 tRealSize += sizeof(drawfile_jpeg) + tImageSize;
447 tSize = ROUND4(tRealSize);
448 vExtendDiagramSize(pDiag, tSize);
449 pNew = xmalloc(tSize);
450 memset(pNew, 0, tSize);
451 pNew->type = drawfile_TYPE_JPEG;
452 pNew->size = tSize;
453 pNew->data.jpeg.bbox.min.x = (int)pDiag->lXleft;
454 pNew->data.jpeg.bbox.min.y = (int)pDiag->lYtop;
455 pNew->data.jpeg.bbox.max.x = (int)(pDiag->lXleft + lWidth);
456 pNew->data.jpeg.bbox.max.y = (int)(pDiag->lYtop + lHeight);
457 pNew->data.jpeg.width = (int)lWidth;
458 pNew->data.jpeg.height = (int)lHeight;
459 pNew->data.jpeg.xdpi = 90;
460 pNew->data.jpeg.ydpi = 90;
461 pNew->data.jpeg.trfm.entries[0][0] = 0x10000;
462 pNew->data.jpeg.trfm.entries[0][1] = 0;
463 pNew->data.jpeg.trfm.entries[1][0] = 0;
464 pNew->data.jpeg.trfm.entries[1][1] = 0x10000;
465 pNew->data.jpeg.trfm.entries[2][0] = (int)pDiag->lXleft;
466 pNew->data.jpeg.trfm.entries[2][1] = (int)pDiag->lYtop;
467 pNew->data.jpeg.len = tImageSize;
468 memcpy(pNew->data.jpeg.data, pucImage, tImageSize);
469 break;
470 default:
471 DBG_DEC(pImg->eImageType);
472 pNew = NULL;
473 break;
476 Error_CheckFatal(Drawfile_AppendObject(&pDiag->tInfo,
477 pDiag->tMemorySize, pNew, TRUE));
478 pNew = xfree(pNew);
479 pDiag->lXleft = 0;
480 } /* end of vImage2Diagram */
483 * bAddDummyImage - add a dummy image
485 * return TRUE when successful, otherwise FALSE
487 BOOL
488 bAddDummyImage(diagram_type *pDiag, const imagedata_type *pImg)
490 drawfile_object *pNew;
491 int *piTmp;
492 long lWidth, lHeight;
493 size_t tRealSize, tSize;
495 TRACE_MSG("bAddDummyImage");
497 fail(pDiag == NULL);
498 fail(pImg == NULL);
499 fail(pDiag->lXleft < 0);
501 if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
502 return FALSE;
505 DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
507 lWidth = lPoints2DrawUnits(pImg->iHorSizeScaled);
508 lHeight = lPoints2DrawUnits(pImg->iVerSizeScaled);
510 pDiag->lYtop -= lHeight;
512 tRealSize = offsetof(drawfile_object, data);
513 tRealSize += sizeof(drawfile_path) + (14 - 1) * sizeof(int);
514 tSize = ROUND4(tRealSize);
515 vExtendDiagramSize(pDiag, tSize);
516 pNew = xmalloc(tSize);
517 memset(pNew, 0, tSize);
518 pNew->type = drawfile_TYPE_PATH;
519 pNew->size = tSize;
520 pNew->data.path.bbox.min.x = (int)pDiag->lXleft;
521 pNew->data.path.bbox.min.y = (int)pDiag->lYtop;
522 pNew->data.path.bbox.max.x = (int)(pDiag->lXleft + lWidth);
523 pNew->data.path.bbox.max.y = (int)(pDiag->lYtop + lHeight);
524 pNew->data.path.fill.value = -1;
525 pNew->data.path.outline.value = 0x4d4d4d00; /* Gray 70 percent */
526 pNew->data.path.width = (int)lMilliPoints2DrawUnits(500);
527 pNew->data.path.style.flags = 0;
528 pNew->data.path.style.reserved = 0;
529 pNew->data.path.style.cap_width = 0;
530 pNew->data.path.style.cap_length = 0;
531 piTmp = pNew->data.path.path;
532 *piTmp++ = drawfile_PATH_MOVE_TO;
533 *piTmp++ = pNew->data.path.bbox.min.x;
534 *piTmp++ = pNew->data.path.bbox.min.y;
535 *piTmp++ = drawfile_PATH_LINE_TO;
536 *piTmp++ = pNew->data.path.bbox.min.x;
537 *piTmp++ = pNew->data.path.bbox.max.y;
538 *piTmp++ = drawfile_PATH_LINE_TO;
539 *piTmp++ = pNew->data.path.bbox.max.x;
540 *piTmp++ = pNew->data.path.bbox.max.y;
541 *piTmp++ = drawfile_PATH_LINE_TO;
542 *piTmp++ = pNew->data.path.bbox.max.x;
543 *piTmp++ = pNew->data.path.bbox.min.y;
544 *piTmp++ = drawfile_PATH_CLOSE_LINE;
545 *piTmp++ = drawfile_PATH_END_PATH;
547 Error_CheckFatal(Drawfile_AppendObject(&pDiag->tInfo,
548 pDiag->tMemorySize, pNew, TRUE));
549 pNew = xfree(pNew);
550 pDiag->lXleft = 0;
551 return TRUE;
552 } /* end of bAddDummyImage */
555 * vMove2NextLine - move to the next line
557 void
558 vMove2NextLine(diagram_type *pDiag, drawfile_fontref tFontRef,
559 USHORT usFontSize)
561 long l20;
563 TRACE_MSG("vMove2NextLine");
565 fail(pDiag == NULL);
566 fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
568 if (tFontRef == 0) {
569 l20 = Drawfile_ScreenToDraw(32 + 3);
570 } else {
571 l20 = lWord2DrawUnits20(usFontSize);
573 pDiag->lYtop -= l20;
574 } /* end of vMove2NextLine */
577 * Create an start of paragraph (Phase 1)
579 void
580 vStartOfParagraph1(diagram_type *pDiag, long lBeforeIndentation)
582 TRACE_MSG("vStartOfParagraph1");
584 fail(pDiag == NULL);
585 fail(lBeforeIndentation < 0);
587 pDiag->lXleft = 0;
588 pDiag->lYtop -= lMilliPoints2DrawUnits(lBeforeIndentation);
589 } /* end of vStartOfParagraph1 */
592 * Create an start of paragraph (Phase 2)
593 * DUMMY function
595 void
596 vStartOfParagraph2(diagram_type *pDiag)
598 TRACE_MSG("vStartOfParagraph2");
599 } /* end of vStartOfParagraph2 */
602 * Create an end of paragraph
604 void
605 vEndOfParagraph(diagram_type *pDiag,
606 drawfile_fontref tFontRef, USHORT usFontSize, long lAfterIndentation)
608 TRACE_MSG("vEndOfParagraph");
610 fail(pDiag == NULL);
611 fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
612 fail(lAfterIndentation < 0);
614 pDiag->lXleft = 0;
615 pDiag->lYtop -= lMilliPoints2DrawUnits(lAfterIndentation);
616 } /* end of vEndOfParagraph */
619 * Create an end of page
621 void
622 vEndOfPage(diagram_type *pDiag, long lAfterIndentation, BOOL bNewSection)
624 TRACE_MSG("vEndOfPage");
626 fail(pDiag == NULL);
627 fail(lAfterIndentation < 0);
629 pDiag->lXleft = 0;
630 pDiag->lYtop -= lMilliPoints2DrawUnits(lAfterIndentation);
631 } /* end of vEndOfPage */
634 * vSetHeaders - set the headers
635 * DUMMY function
637 void
638 vSetHeaders(diagram_type *pDiag, USHORT usIstd)
640 TRACE_MSG("vSetHeaders");
641 } /* end of vSetHeaders */
644 * Create a start of list
645 * DUMMY function
647 void
648 vStartOfList(diagram_type *pDiag, UCHAR ucNFC, BOOL bIsEndOfTable)
650 TRACE_MSG("vStartOfList");
651 } /* end of vStartOfList */
654 * Create an end of list
655 * DUMMY function
657 void
658 vEndOfList(diagram_type *pDiag)
660 TRACE_MSG("vEndOfList");
661 } /* end of vEndOfList */
664 * Create a start of a list item
665 * DUMMY function
667 void
668 vStartOfListItem(diagram_type *pDiag, BOOL bNoMarks)
670 TRACE_MSG("vStartOfListItem");
671 } /* end of vStartOfListItem */
674 * Create an end of a table
675 * DUMMY function
677 void
678 vEndOfTable(diagram_type *pDiag)
680 TRACE_MSG("vEndOfTable");
681 } /* end of vEndTable */
684 * Add a table row
685 * DUMMY function
687 * Returns TRUE when conversion type is XML
689 BOOL
690 bAddTableRow(diagram_type *pDiag, char **aszColTxt,
691 int iNbrOfColumns, const short *asColumnWidth, UCHAR ucBorderInfo)
693 TRACE_MSG("bAddTableRow");
695 return FALSE;
696 } /* end of bAddTableRow */
699 * vForceRedraw - force a redraw of the main window
701 static void
702 vForceRedraw(diagram_type *pDiag)
704 window_state tWindowState;
705 window_redrawblock tRedraw;
706 int x0, y0, x1, y1;
708 TRACE_MSG("vForceRedraw");
710 fail(pDiag == NULL);
712 DBG_DEC(pDiag->iScaleFactorCurr);
714 /* Read the size of the current diagram */
715 Drawfile_QueryBox(&pDiag->tInfo, &tRedraw.rect, TRUE);
716 /* Adjust the size of the work area */
717 x0 = tRedraw.rect.min.x * pDiag->iScaleFactorCurr / 100 - 1;
718 y0 = tRedraw.rect.min.y * pDiag->iScaleFactorCurr / 100 - 1;
719 x1 = tRedraw.rect.max.x * pDiag->iScaleFactorCurr / 100 + 1;
720 y1 = tRedraw.rect.max.y * pDiag->iScaleFactorCurr / 100 + 1;
721 /* Work area extension */
722 x0 -= WORKAREA_EXTENSION;
723 y0 -= WORKAREA_EXTENSION;
724 x1 += WORKAREA_EXTENSION;
725 y1 += WORKAREA_EXTENSION;
726 Window_SetExtent(pDiag->tMainWindow, x0, y0, x1, y1);
727 /* Widen the box slightly to be sure all the edges are drawn */
728 x0 -= 5;
729 y0 -= 5;
730 x1 += 5;
731 y1 += 5;
732 /* Force the redraw */
733 Window_ForceRedraw(pDiag->tMainWindow, x0, y0, x1, y1);
734 /* Reopen the window to show the correct size */
735 Error_CheckFatal(Wimp_GetWindowState(pDiag->tMainWindow, &tWindowState));
736 tWindowState.openblock.behind = -1;
737 Error_CheckFatal(Wimp_OpenWindow(&tWindowState.openblock));
738 } /* end of vForceRedraw */
741 * vShowDiagram - put the diagram on the screen
743 void
744 vShowDiagram(diagram_type *pDiag)
746 wimp_box tRect;
747 int x0, y0, x1, y1;
749 TRACE_MSG("vShowDiagram");
751 fail(pDiag == NULL);
753 Window_Show(pDiag->tMainWindow, open_NEARLAST);
754 Drawfile_QueryBox(&pDiag->tInfo, &tRect, TRUE);
755 /* Work area extension */
756 x0 = tRect.min.x - WORKAREA_EXTENSION;
757 y0 = tRect.min.y - WORKAREA_EXTENSION;
758 x1 = tRect.max.x + WORKAREA_EXTENSION;
759 y1 = tRect.max.y + WORKAREA_EXTENSION;
760 Window_SetExtent(pDiag->tMainWindow, x0, y0, x1, y1);
761 vForceRedraw(pDiag);
762 } /* end of vShowDiagram */
765 * vMainButtonClick - handle mouse buttons clicks for the main screen
767 void
768 vMainButtonClick(mouse_block *pMouse)
770 caret_block tCaret;
771 window_state ws;
773 TRACE_MSG("vMainButtonClick");
775 fail(pMouse == NULL);
777 DBG_DEC(pMouse->button.data.select);
778 DBG_DEC(pMouse->button.data.adjust);
779 DBG_DEC(pMouse->window);
780 DBG_DEC(pMouse->icon);
782 if (pMouse->window >= 0 &&
783 pMouse->icon == -1 &&
784 (pMouse->button.data.select || pMouse->button.data.adjust)) {
785 /* Get the input focus */
786 Error_CheckFatal(Wimp_GetWindowState(pMouse->window, &ws));
787 tCaret.window = pMouse->window;
788 tCaret.icon = -1;
789 tCaret.offset.x = pMouse->pos.x - ws.openblock.screenrect.min.x;
790 tCaret.offset.y = pMouse->pos.y - ws.openblock.screenrect.max.y;
791 tCaret.height = (int)BIT(25);
792 tCaret.index = 0;
793 Error_CheckFatal(Wimp_SetCaretPosition(&tCaret));
795 } /* end of vMainButtonClick */
798 * bMainKeyPressed - handle pressed keys for the main window
800 BOOL
801 bMainKeyPressed(event_pollblock *pEvent, void *pvReference)
803 diagram_type *pDiag;
805 TRACE_MSG("bMainKeyPressed");
807 fail(pEvent == NULL);
808 fail(pEvent->type != event_KEY);
809 fail(pvReference == NULL);
811 pDiag = (diagram_type *)pvReference;
813 fail(pEvent->data.key.caret.window != pDiag->tMainWindow);
816 switch (pEvent->data.key.code) {
817 case keycode_CTRL_F2: /* Ctrl F2 */
818 bDestroyDiagram(pEvent, pvReference);
819 break;
820 case keycode_F3: /* F3 */
821 bSaveDrawfile(pEvent, pvReference);
822 break;
823 case keycode_SHIFT_F3: /* Shift F3 */
824 bSaveTextfile(pEvent, pvReference);
825 break;
826 default:
827 DBG_DEC(pEvent->data.key.code);
828 Error_CheckFatal(Wimp_ProcessKey(pEvent->data.key.code));
830 return TRUE;
831 } /* end of bMainKeyPressed */
834 * bRedrawMainWindow - redraw the main window
836 BOOL
837 bRedrawMainWindow(event_pollblock *pEvent, void *pvReference)
839 window_redrawblock tBlock;
840 diagram_type *pDiag;
841 drawfile_info *pInfo;
842 double dScaleFactor;
843 BOOL bMore;
845 TRACE_MSG("bRedrawMainWindow");
847 fail(pEvent == NULL);
848 fail(pEvent->type != event_REDRAW);
849 fail(pvReference == NULL);
851 pDiag = (diagram_type *)pvReference;
853 fail(pDiag->tMainWindow != pEvent->data.openblock.window);
854 fail(pDiag->iScaleFactorCurr < MIN_SCALE_FACTOR);
855 fail(pDiag->iScaleFactorCurr > MAX_SCALE_FACTOR);
857 dScaleFactor = (double)pDiag->iScaleFactorCurr / 100.0;
858 pInfo = &pDiag->tInfo;
860 tBlock.window = pEvent->data.openblock.window;
861 Error_CheckFatal(Wimp_RedrawWindow(&tBlock, &bMore));
863 /* If there is no real diagram just go thru the motions */
864 while (bMore) {
865 if (pInfo->data != NULL && pInfo->length != 0) {
866 Error_CheckFatal(Drawfile_RenderDiagram(pInfo,
867 &tBlock, dScaleFactor));
869 Error_CheckFatal(Wimp_GetRectangle(&tBlock, &bMore));
871 return TRUE;
872 } /* end of bRedrawMainWindow */
875 * bScaleOpenAction - action to be taken when the Scale view window opens
877 BOOL
878 bScaleOpenAction(event_pollblock *pEvent, void *pvReference)
880 window_state tWindowState;
881 diagram_type *pDiag;
883 TRACE_MSG("bScaleOpenAction");
885 fail(pEvent == NULL);
886 fail(pEvent->type != event_SEND);
887 fail(pEvent->data.message.header.action != message_MENUWARN);
888 fail(pvReference == NULL);
890 pDiag = (diagram_type *)pvReference;
892 if (menu_currentopen != pDiag->pSaveMenu ||
893 pEvent->data.message.data.menuwarn.selection[0] != SAVEMENU_SCALEVIEW) {
894 return FALSE;
897 Error_CheckFatal(Wimp_GetWindowState(pDiag->tScaleWindow,
898 &tWindowState));
899 if (tWindowState.flags.data.open) {
900 /* The window is already open */
901 return TRUE;
904 DBG_MSG("vScaleOpenAction for real");
906 pDiag->iScaleFactorTemp = pDiag->iScaleFactorCurr;
907 vUpdateWriteableNumber(pDiag->tScaleWindow,
908 SCALE_SCALE_WRITEABLE, pDiag->iScaleFactorTemp);
909 Window_Show(pDiag->tScaleWindow, open_UNDERPOINTER);
910 return TRUE;
911 } /* end of bScaleOpenAction */
914 * vSetTitle - set the title of a window
916 void
917 vSetTitle(diagram_type *pDiag)
919 char szTitle[WINDOW_TITLE_LEN];
921 TRACE_MSG("vSetTitle");
923 fail(pDiag == NULL);
924 fail(pDiag->szFilename[0] == '\0');
926 (void)sprintf(szTitle, "%.*s at %d%%",
927 FILENAME_TITLE_LEN,
928 pDiag->szFilename,
929 pDiag->iScaleFactorCurr % 1000);
930 if (strlen(pDiag->szFilename) > FILENAME_TITLE_LEN) {
931 szTitle[FILENAME_TITLE_LEN - 1] = OUR_ELLIPSIS;
934 Window_SetTitle(pDiag->tMainWindow, szTitle);
935 } /* end of vSetTitle */
938 * vScaleButtonClick - handle a mouse button click in the Scale view window
940 void
941 vScaleButtonClick(mouse_block *pMouse, diagram_type *pDiag)
943 BOOL bCloseWindow, bRedraw;
945 TRACE_MSG("vScaleButtonClick");
947 fail(pMouse == NULL || pDiag == NULL);
948 fail(pMouse->window != pDiag->tScaleWindow);
950 bCloseWindow = FALSE;
951 bRedraw = FALSE;
952 switch (pMouse->icon) {
953 case SCALE_CANCEL_BUTTON:
954 bCloseWindow = TRUE;
955 pDiag->iScaleFactorTemp = pDiag->iScaleFactorCurr;
956 break;
957 case SCALE_SCALE_BUTTON:
958 bCloseWindow = TRUE;
959 bRedraw = pDiag->iScaleFactorCurr != pDiag->iScaleFactorTemp;
960 pDiag->iScaleFactorCurr = pDiag->iScaleFactorTemp;
961 break;
962 case SCALE_50_PCT:
963 pDiag->iScaleFactorTemp = 50;
964 break;
965 case SCALE_75_PCT:
966 pDiag->iScaleFactorTemp = 75;
967 break;
968 case SCALE_100_PCT:
969 pDiag->iScaleFactorTemp = 100;
970 break;
971 case SCALE_150_PCT:
972 pDiag->iScaleFactorTemp = 150;
973 break;
974 default:
975 DBG_DEC(pMouse->icon);
976 break;
978 if (bCloseWindow) {
979 /* Close the scale window */
980 Error_CheckFatal(Wimp_CloseWindow(pMouse->window));
981 if (bRedraw) {
982 /* Redraw the main window */
983 vSetTitle(pDiag);
984 vForceRedraw(pDiag);
986 } else {
987 vUpdateWriteableNumber(pMouse->window,
988 SCALE_SCALE_WRITEABLE,
989 pDiag->iScaleFactorTemp);
991 } /* end of vScaleButtonClick */
994 * bScaleKeyPressed - handle pressed keys for the scale window
996 BOOL
997 bScaleKeyPressed(event_pollblock *pEvent, void *pvReference)
999 icon_block tIcon;
1000 diagram_type *pDiag;
1001 caret_block *pCaret;
1002 char *pcChar;
1003 int iTmp;
1005 TRACE_MSG("bScaleKeyPressed");
1007 fail(pEvent == NULL);
1008 fail(pEvent->type != event_KEY);
1009 fail(pvReference == NULL);
1011 pCaret = &pEvent->data.key.caret;
1012 pDiag = (diagram_type *)pvReference;
1014 fail(pEvent->data.key.caret.window != pDiag->tScaleWindow);
1016 DBG_DEC_C(pCaret->icon != SCALE_SCALE_WRITEABLE, pCaret->icon);
1017 DBG_DEC_C(pCaret->icon == SCALE_SCALE_WRITEABLE, pEvent->data.key.code);
1019 if (pEvent->data.key.code != '\r' ||
1020 pCaret->icon != SCALE_SCALE_WRITEABLE) {
1021 Error_CheckFatal(Wimp_ProcessKey(pEvent->data.key.code));
1022 return TRUE;
1025 Error_CheckFatal(Wimp_GetIconState(pCaret->window, pCaret->icon, &tIcon));
1026 if (!tIcon.flags.data.text || !tIcon.flags.data.indirected) {
1027 werr(1, "Icon %d must be indirected text", (int)pCaret->icon);
1029 iTmp = (int)strtol(tIcon.data.indirecttext.buffer, &pcChar, 10);
1030 if (*pcChar != '\0' && *pcChar != '\r') {
1031 DBG_DEC(*pcChar);
1032 } else if (iTmp < MIN_SCALE_FACTOR) {
1033 pDiag->iScaleFactorTemp = MIN_SCALE_FACTOR;
1034 } else if (iTmp > MAX_SCALE_FACTOR) {
1035 pDiag->iScaleFactorTemp = MAX_SCALE_FACTOR;
1036 } else {
1037 pDiag->iScaleFactorTemp = iTmp;
1039 pDiag->iScaleFactorCurr = pDiag->iScaleFactorTemp;
1040 /* Close the scale window */
1041 Error_CheckFatal(Wimp_CloseWindow(pCaret->window));
1042 /* Redraw the main window */
1043 vSetTitle(pDiag);
1044 vForceRedraw(pDiag);
1045 return TRUE;
1046 } /* end of bScaleKeyPressed */