home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / anwor032.zip / antiword.0.32 / draw.c < prev    next >
C/C++ Source or Header  |  2001-06-13  |  25KB  |  978 lines

  1. /*
  2.  * draw.c
  3.  * Copyright (C) 1998-2001 A.J. van Os; Released under GPL
  4.  *
  5.  * Description:
  6.  * Functions to deal with the Draw format
  7.  */
  8.  
  9. #include <stdlib.h>
  10. #include <ctype.h>
  11. #include <string.h>
  12. #include "akbd.h"
  13. #include "flex.h"
  14. #include "wimp.h"
  15. #include "template.h"
  16. #include "wimpt.h"
  17. #include "win.h"
  18. #include "antiword.h"
  19.  
  20. /* The work area must be a little bit larger than the diagram */
  21. #define WORKAREA_EXTENSION        5
  22. /* Diagram memory */
  23. #define INITIAL_SIZE        32768    /* 32k */
  24. #define EXTENSION_SIZE         4096    /*  4k */
  25. /* Main window title */
  26. #define WINDOW_TITLE_LEN       28
  27. #define FILENAME_TITLE_LEN    (WINDOW_TITLE_LEN - 10)
  28.  
  29. static BOOL    (*bDrawRenderDiag)(draw_diag *,
  30.             draw_redrawstr *, double, draw_error *) = NULL;
  31.  
  32. /*
  33.  * vCreateMainWindow - create the Main Window
  34.  *
  35.  * remark: does not return if the Main Window can't be created
  36.  */
  37. static wimp_w
  38. tCreateMainWindow(void)
  39. {
  40.     static int    iY = 0;
  41.     template    *pTemplate;
  42.     wimp_w        tMainWindow;
  43.  
  44.     /* Find and check the template */
  45.     pTemplate = template_find("MainWindow");
  46.     if (pTemplate == NULL) {
  47.         werr(1, "The 'MainWindow' template can't be found");
  48.     }
  49.     pTemplate = template_copy(pTemplate);
  50.     if (pTemplate == NULL) {
  51.         werr(1, "I can't copy the 'MainWindow' template");
  52.     }
  53.     if ((pTemplate->window.titleflags & wimp_INDIRECT) !=
  54.                             wimp_INDIRECT) {
  55.         werr(1,
  56.     "The title of the 'MainWindow' template must be indirected text");
  57.     }
  58.     if (pTemplate->window.title.indirecttext.bufflen < WINDOW_TITLE_LEN) {
  59.         werr(1, "The 'MainWindow' title needs %d characters",
  60.             WINDOW_TITLE_LEN);
  61.     }
  62.  
  63.     /*
  64.      * Leave 48 OS units between two windows, as recommended by the
  65.      * Style guide. And try to stay away from the iconbar.
  66.      */
  67.     if (pTemplate->window.box.y0 < iY + 130) {
  68.         iY = 48;
  69.     } else {
  70.         pTemplate->window.box.y0 -= iY;
  71.         pTemplate->window.box.y1 -= iY;
  72.         iY += 48;
  73.     }
  74.  
  75.     /* Create the window */
  76.     wimpt_noerr(wimp_create_wind(&pTemplate->window, &tMainWindow));
  77.     return tMainWindow;
  78. } /* end of tCreateMainWindow */
  79.  
  80. /*
  81.  * vCreateScaleWindow - create the Scale view Window
  82.  *
  83.  * remark: does not return if the Scale view Window can't be created
  84.  */
  85. static wimp_w
  86. tCreateScaleWindow(void)
  87. {
  88.     wimp_wind    *pw;
  89.     wimp_w        tScaleWindow;
  90.  
  91.     pw = template_syshandle("ScaleView");
  92.     if (pw == NULL) {
  93.         werr(1, "Template 'ScaleView' can't be found");
  94.     }
  95.     wimpt_noerr(wimp_create_wind(pw, &tScaleWindow));
  96.     return tScaleWindow;
  97. } /* end of tCreateScaleWindow */
  98.  
  99. /*
  100.  * pCreateDiagram - create and initialize a diagram
  101.  *
  102.  * remark: does not return if the diagram can't be created
  103.  */
  104. diagram_type *
  105. pCreateDiagram(const char *szTask, const char *szFilename)
  106. {
  107.     diagram_type    *pDiag;
  108.     options_type    tOptions;
  109.     wimp_w        tMainWindow, tScaleWindow;
  110.     draw_box    tBox;
  111.  
  112.     DBG_MSG("pCreateDiagram");
  113.  
  114.     fail(szTask == NULL || szTask[0] == '\0');
  115.  
  116.     /* Create the main window */
  117.     tMainWindow = tCreateMainWindow();
  118.     /* Create the scale view window */
  119.     tScaleWindow = tCreateScaleWindow();
  120.  
  121.     /* Get the necessary memory */
  122.     pDiag = xmalloc(sizeof(diagram_type));
  123.     if (flex_alloc((flex_ptr)&pDiag->tInfo.data, INITIAL_SIZE) != 1) {
  124.         werr(1, "Memory allocation failed, unable to continue");
  125.     }
  126.  
  127.     /* Determine which function to use for rendering the diagram */
  128.     if (iGetRiscOsVersion() >= 360) {
  129.         /* Home brew for RISC OS 3.6 functionality */
  130.           bDrawRenderDiag = bDrawRenderDiag360;
  131.       } else {
  132.         /* The function from RISC_OSLib */
  133.         bDrawRenderDiag = draw_render_diag;
  134.     }
  135.  
  136.     /* Initialize the diagram */
  137.     vGetOptions(&tOptions);
  138.     pDiag->tMainWindow = tMainWindow;
  139.     pDiag->tScaleWindow = tScaleWindow;
  140.     pDiag->iScaleFactorCurr = tOptions.iScaleFactor;
  141.     pDiag->iScaleFactorTemp = tOptions.iScaleFactor;
  142.     pDiag->tMemorySize = INITIAL_SIZE;
  143.     tBox.x0 = 0;
  144.     tBox.y0 = -(draw_screenToDraw(32 + 3) * 8 + 1);
  145.     tBox.x1 = draw_screenToDraw(16) * MIN_SCREEN_WIDTH + 1;
  146.     tBox.y1 = 0;
  147.     draw_create_diag(&pDiag->tInfo, (char *)szTask, tBox);
  148.     DBG_DEC(pDiag->tInfo.length);
  149.     pDiag->lXleft = 0;
  150.     pDiag->lYtop = 0;
  151.     strncpy(pDiag->szFilename,
  152.             szBasename(szFilename), sizeof(pDiag->szFilename) - 1);
  153.     pDiag->szFilename[sizeof(pDiag->szFilename) - 1] = '\0';
  154.     /* Return success */
  155.     return pDiag;
  156. } /* end of pCreateDiagram */
  157.  
  158. /*
  159.  * vDestroyDiagram - remove a diagram by freeing the memory it uses
  160.  */
  161. static void
  162. vDestroyDiagram(wimp_w tWindow, diagram_type *pDiag)
  163. {
  164.     DBG_MSG("vDestroyDiagram");
  165.  
  166.     fail(pDiag != NULL && pDiag->tMainWindow != tWindow);
  167.  
  168.     wimpt_noerr(wimp_close_wind(tWindow));
  169.     if (pDiag == NULL) {
  170.         return;
  171.     }
  172.     if (pDiag->tInfo.data != NULL && pDiag->tMemorySize != 0) {
  173.         flex_free((flex_ptr)&pDiag->tInfo.data);
  174.     }
  175.     pDiag = xfree(pDiag);
  176. } /* end of vDestroyDiagram */
  177.  
  178. /*
  179.  * vPrintDrawError - print an error reported by a draw function
  180.  */
  181. static void
  182. vPrintDrawError(draw_error *pError)
  183. {
  184.     DBG_MSG("vPrintDrawError");
  185.  
  186.     fail(pError == NULL);
  187.  
  188.     switch (pError->type) {
  189.     case DrawOSError:
  190.         DBG_DEC(pError->err.os.errnum);
  191.         DBG_MSG(pError->err.os.errmess);
  192.         werr(1, "DrawOSError: %d: %s",
  193.             pError->err.os.errnum, pError->err.os.errmess);
  194.         break;
  195.     case DrawOwnError:
  196.         DBG_DEC(pError->err.draw.code);
  197.         DBG_HEX(pError->err.draw.location);
  198.         werr(1, "DrawOwnError: Code %d - Location &%x",
  199.             pError->err.draw.code, pError->err.draw.location);
  200.         break;
  201.     case None:
  202.     default:
  203.         break;
  204.     }
  205. } /* end of vPrintDrawError */
  206.  
  207. /*
  208.  * vExtendDiagramSize - make sure the diagram is big enough
  209.  */
  210. static void
  211. vExtendDiagramSize(diagram_type *pDiag, size_t tSize)
  212. {
  213.     fail(pDiag == NULL || tSize % 4 != 0);
  214.  
  215.     while (pDiag->tInfo.length + tSize > pDiag->tMemorySize) {
  216.         if (flex_extend((flex_ptr)&pDiag->tInfo.data,
  217.                 pDiag->tMemorySize + EXTENSION_SIZE) != 1) {
  218.             werr(1, "Memory extend failed, unable to continue");
  219.         }
  220.         pDiag->tMemorySize += EXTENSION_SIZE;
  221.         NO_DBG_DEC(pDiag->tMemorySize);
  222.     }
  223. } /* end of vExtendDiagramSize */
  224.  
  225. /*
  226.  * vAddFonts2Diagram - add a font list to a diagram
  227.  */
  228. void
  229. vAddFonts2Diagram(diagram_type *pDiag)
  230. {
  231.     draw_objectType    tNew;
  232.     draw_error    tError;
  233.     draw_object    tHandle;
  234.     const font_table_type    *pTmp;
  235.     char    *pcTmp;
  236.     size_t    tRealSize, tSize;
  237.     int    iCount;
  238.  
  239.     fail(pDiag == NULL);
  240.  
  241.     if (tGetFontTableLength() == 0) {
  242.         return;
  243.     }
  244.     tRealSize = sizeof(draw_fontliststrhdr);
  245.     pTmp = NULL;
  246.     while ((pTmp = pGetNextFontTableRecord(pTmp)) != NULL) {
  247.         tRealSize += 2 + strlen(pTmp->szOurFontname);
  248.     }
  249.     tSize = ROUND4(tRealSize);
  250.     vExtendDiagramSize(pDiag, tSize);
  251.     tNew.fontList = xmalloc(tSize);
  252.     tNew.fontList->tag = draw_OBJFONTLIST;
  253.     tNew.fontList->size = tSize;
  254.     pcTmp = (char *)&tNew.fontList->fontref;
  255.     iCount = 0;
  256.     pTmp = NULL;
  257.     while ((pTmp = pGetNextFontTableRecord(pTmp)) != NULL) {
  258.         *pcTmp = ++iCount;
  259.         pcTmp++;
  260.         strcpy(pcTmp, pTmp->szOurFontname);
  261.         pcTmp += 1 + strlen(pTmp->szOurFontname);
  262.     }
  263.     memset((char *)tNew.fontList + tRealSize, 0, tSize - tRealSize);
  264.     if (draw_createObject(&pDiag->tInfo, tNew, draw_LastObject,
  265.                         TRUE, &tHandle, &tError)) {
  266.         draw_translateText(&pDiag->tInfo);
  267.     } else {
  268.         DBG_MSG("draw_createObject() failed");
  269.         vPrintDrawError(&tError);
  270.     }
  271.     tNew.fontList = xfree(tNew.fontList);
  272. } /* end of vAddFonts2Diagram */
  273.  
  274. /*
  275.  * vSubstring2Diagram - put a sub string into a diagram
  276.  */
  277. void
  278. vSubstring2Diagram(diagram_type *pDiag,
  279.     char *szString, int iStringLength, long lStringWidth,
  280.     int iColor, unsigned char ucFontstyle, draw_fontref tFontRef,
  281.     int iFontsize, int iMaxFontsize)
  282. {
  283.     draw_objectType    tNew;
  284.     draw_error    tError;
  285.     draw_object    tHandle;
  286.     long    lSizeX, lSizeY, lOffset, l20;
  287.     size_t    tRealSize, tSize;
  288.  
  289.     fail(pDiag == NULL || szString == NULL);
  290.     fail(pDiag->lXleft < 0);
  291.     fail(iStringLength != strlen(szString));
  292.     fail(iFontsize < MIN_FONT_SIZE || iFontsize > MAX_FONT_SIZE);
  293.     fail(iMaxFontsize < MIN_FONT_SIZE || iMaxFontsize > MAX_FONT_SIZE);
  294.     fail(iFontsize > iMaxFontsize);
  295.  
  296.     if (szString[0] == '\0' || iStringLength <= 0) {
  297.         return;
  298.     }
  299.  
  300.     if (tFontRef == 0) {
  301.         lOffset = draw_screenToDraw(2);
  302.         l20 = draw_screenToDraw(32 + 3);
  303.         lSizeX = draw_screenToDraw(16);
  304.         lSizeY = draw_screenToDraw(32);
  305.     } else {
  306.         lOffset = lToBaseLine(iMaxFontsize);
  307.         l20 = lWord2DrawUnits20(iMaxFontsize);
  308.         lSizeX = lWord2DrawUnits00(iFontsize);
  309.         lSizeY = lWord2DrawUnits00(iFontsize);
  310.     }
  311.  
  312.     tRealSize = sizeof(draw_textstr) + iStringLength;
  313.     tSize = ROUND4(tRealSize);
  314.     vExtendDiagramSize(pDiag, tSize);
  315.     tNew.text = xmalloc(tSize);
  316.     tNew.text->tag = draw_OBJTEXT;
  317.     tNew.text->size = tSize;
  318.     tNew.text->bbox.x0 = (int)pDiag->lXleft;
  319.     tNew.text->bbox.y0 = (int)pDiag->lYtop;
  320.     tNew.text->bbox.x1 = (int)(pDiag->lXleft + lStringWidth);
  321.     tNew.text->bbox.y1 = (int)(pDiag->lYtop + l20);
  322.     tNew.text->textcolour = uiColor2Color(iColor);
  323.     tNew.text->background = 0xffffff00;    /* White */
  324.     tNew.text->textstyle.fontref = tFontRef;
  325.     tNew.text->textstyle.reserved8 = 0;
  326.     tNew.text->textstyle.reserved16 = 0;
  327.     tNew.text->fsizex = (int)lSizeX;
  328.     tNew.text->fsizey = (int)lSizeY;
  329.     tNew.text->coord.x = (int)pDiag->lXleft;
  330.     tNew.text->coord.y = (int)(pDiag->lYtop + lOffset);
  331.     strncpy(tNew.text->text, szString, iStringLength);
  332.     tNew.text->text[iStringLength] = '\0';
  333.     memset((char *)tNew.text + tRealSize, 0, tSize - tRealSize);
  334.     if (!draw_createObject(&pDiag->tInfo, tNew, draw_LastObject,
  335.                         TRUE, &tHandle, &tError)) {
  336.         DBG_MSG("draw_createObject() failed");
  337.         vPrintDrawError(&tError);
  338.     }
  339.     tNew.text = xfree(tNew.text);
  340.     draw_translateText(&pDiag->tInfo);
  341.     pDiag->lXleft += lStringWidth;
  342. } /* end of vSubstring2Diagram */
  343.  
  344. /*
  345.  * vImage2Diagram - put an image into a diagram
  346.  */
  347. void
  348. vImage2Diagram(diagram_type *pDiag, const imagedata_type *pImg,
  349.     unsigned char *pucImage, size_t tImageSize)
  350. {
  351.       draw_objectType    tTmp;
  352.       draw_imageType    tNew;
  353.     draw_error    tError;
  354.     draw_object    tHandle;
  355.     long    lWidth, lHeight;
  356.     size_t    tRealSize, tSize;
  357.  
  358.     DBG_MSG("vImage2Diagram");
  359.  
  360.     fail(pDiag == NULL);
  361.     fail(pImg == NULL);
  362.     fail(pDiag->lXleft < 0);
  363.     fail(pImg->eImageType != imagetype_is_dib &&
  364.          pImg->eImageType != imagetype_is_jpeg);
  365.  
  366.     DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
  367.  
  368.     lWidth = lPoints2DrawUnits(pImg->iHorSizeScaled);
  369.     lHeight = lPoints2DrawUnits(pImg->iVerSizeScaled);
  370.  
  371.     pDiag->lYtop -= lHeight;
  372.  
  373.     switch (pImg->eImageType) {
  374.     case imagetype_is_dib:
  375.         tRealSize = sizeof(draw_spristrhdr) + tImageSize;
  376.         tSize = ROUND4(tRealSize);
  377.         vExtendDiagramSize(pDiag, tSize);
  378.         tNew.sprite = xmalloc(tSize);
  379.         tNew.sprite->tag = draw_OBJSPRITE;
  380.         tNew.sprite->size = tSize;
  381.         tNew.sprite->bbox.x0 = (int)pDiag->lXleft;
  382.         tNew.sprite->bbox.y0 = (int)pDiag->lYtop;
  383.         tNew.sprite->bbox.x1 = (int)(pDiag->lXleft + lWidth);
  384.         tNew.sprite->bbox.y1 = (int)(pDiag->lYtop + lHeight);
  385.         memcpy(&tNew.sprite->sprite, pucImage, tImageSize);
  386.         memset((char *)tNew.sprite + tRealSize, 0, tSize - tRealSize);
  387.         break;
  388.     case imagetype_is_jpeg:
  389.         tRealSize = sizeof(draw_jpegstrhdr) + tImageSize;
  390.         tSize = ROUND4(tRealSize);
  391.         vExtendDiagramSize(pDiag, tSize);
  392.         tNew.jpeg = xmalloc(tSize);
  393.         tNew.jpeg->tag = draw_OBJJPEG;
  394.         tNew.jpeg->size = tSize;
  395.         tNew.jpeg->bbox.x0 = (int)pDiag->lXleft;
  396.         tNew.jpeg->bbox.y0 = (int)pDiag->lYtop;
  397.         tNew.jpeg->bbox.x1 = (int)(pDiag->lXleft + lWidth);
  398.         tNew.jpeg->bbox.y1 = (int)(pDiag->lYtop + lHeight);
  399.         tNew.jpeg->width = (int)lWidth;
  400.         tNew.jpeg->height = (int)lHeight;
  401.         tNew.jpeg->xdpi = 90;
  402.         tNew.jpeg->ydpi = 90;
  403.         tNew.jpeg->trfm[0] = 0x10000;
  404.         tNew.jpeg->trfm[1] = 0;
  405.         tNew.jpeg->trfm[2] = 0;
  406.         tNew.jpeg->trfm[3] = 0x10000;
  407.         tNew.jpeg->trfm[4] = (int)pDiag->lXleft;
  408.         tNew.jpeg->trfm[5] = (int)pDiag->lYtop;
  409.         tNew.jpeg->len = tImageSize;
  410.         memcpy(&tNew.jpeg->jpeg, pucImage, tImageSize);
  411.         memset((char *)tNew.jpeg + tRealSize, 0, tSize - tRealSize);
  412.         break;
  413.     default:
  414.         DBG_DEC(pImg->eImageType);
  415.         break;
  416.     }
  417.  
  418.     tTmp = *(draw_objectType *)&tNew;
  419.     if (!draw_createObject(&pDiag->tInfo, tTmp, draw_LastObject,
  420.                         TRUE, &tHandle, &tError)) {
  421.         DBG_MSG("draw_createObject() failed");
  422.         vPrintDrawError(&tError);
  423.     }
  424.  
  425.     switch (pImg->eImageType) {
  426.     case imagetype_is_dib:
  427.         tNew.sprite = xfree(tNew.sprite);
  428.         break;
  429.     case imagetype_is_jpeg:
  430.         tNew.jpeg = xfree(tNew.jpeg);
  431.         break;
  432.     default:
  433.         DBG_DEC(pImg->eImageType);
  434.         break;
  435.     }
  436.     pDiag->lXleft = 0;
  437. } /* end of vImage2Diagram */
  438.  
  439. /*
  440.  * bAddDummyImage - add a dummy image
  441.  *
  442.  * return TRUE when successful, otherwise FALSE
  443.  */
  444. BOOL
  445. bAddDummyImage(diagram_type *pDiag, const imagedata_type *pImg)
  446. {
  447.       draw_objectType    tNew;
  448.     draw_error    tError;
  449.     draw_object    tHandle;
  450.     int    *piTmp;
  451.     long    lWidth, lHeight;
  452.     size_t    tRealSize, tSize;
  453.  
  454.     DBG_MSG("bAddDummyImage");
  455.  
  456.     fail(pDiag == NULL);
  457.     fail(pImg == NULL);
  458.     fail(pDiag->lXleft < 0);
  459.  
  460.     if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
  461.         return FALSE;
  462.     }
  463.  
  464.     DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
  465.  
  466.     lWidth = lPoints2DrawUnits(pImg->iHorSizeScaled);
  467.     lHeight = lPoints2DrawUnits(pImg->iVerSizeScaled);
  468.  
  469.     pDiag->lYtop -= lHeight;
  470.  
  471.     tRealSize = sizeof(draw_pathstrhdr) + 14 * sizeof(int);
  472.     tSize = ROUND4(tRealSize);
  473.     vExtendDiagramSize(pDiag, tSize);
  474.     tNew.path = xmalloc(tSize);
  475.     tNew.path->tag = draw_OBJPATH;
  476.     tNew.path->size = tSize;
  477.     tNew.path->bbox.x0 = (int)pDiag->lXleft;
  478.     tNew.path->bbox.y0 = (int)pDiag->lYtop;
  479.     tNew.path->bbox.x1 = (int)(pDiag->lXleft + lWidth);
  480.     tNew.path->bbox.y1 = (int)(pDiag->lYtop + lHeight);
  481.     tNew.path->fillcolour = -1;
  482.     tNew.path->pathcolour = 0x4d4d4d00;    /* Gray 70 percent */
  483.     tNew.path->pathwidth = (int)lMilliPoints2DrawUnits(500);
  484.     tNew.path->pathstyle.joincapwind = 0;
  485.     tNew.path->pathstyle.reserved8 = 0;
  486.     tNew.path->pathstyle.tricapwid = 0;
  487.     tNew.path->pathstyle.tricaphei = 0;
  488.     piTmp = (int *)((char *)tNew.path + sizeof(draw_pathstrhdr));
  489.     *piTmp++ = draw_PathMOVE;
  490.     *piTmp++ = tNew.path->bbox.x0;
  491.     *piTmp++ = tNew.path->bbox.y0;
  492.     *piTmp++ = draw_PathLINE;
  493.     *piTmp++ = tNew.path->bbox.x0;
  494.     *piTmp++ = tNew.path->bbox.y1;
  495.     *piTmp++ = draw_PathLINE;
  496.     *piTmp++ = tNew.path->bbox.x1;
  497.     *piTmp++ = tNew.path->bbox.y1;
  498.     *piTmp++ = draw_PathLINE;
  499.     *piTmp++ = tNew.path->bbox.x1;
  500.     *piTmp++ = tNew.path->bbox.y0;
  501.     *piTmp++ = draw_PathCLOSE;
  502.     *piTmp++ = draw_PathTERM;
  503.     memset((char *)tNew.path + tRealSize, 0, tSize - tRealSize);
  504.     if (!draw_createObject(&pDiag->tInfo, tNew, draw_LastObject,
  505.                         TRUE, &tHandle, &tError)) {
  506.         DBG_MSG("draw_createObject() failed");
  507.         vPrintDrawError(&tError);
  508.     }
  509.     tNew.path = xfree(tNew.path);
  510.     pDiag->lXleft = 0;
  511.     return TRUE;
  512. } /* end of bAddDummyImage */
  513.  
  514. /*
  515.  * vMove2NextLine - move to the next line
  516.  */
  517. void
  518. vMove2NextLine(diagram_type *pDiag, draw_fontref tFontRef, int iFontsize)
  519. {
  520.     long    l20;
  521.  
  522.     fail(pDiag == NULL);
  523.     fail(iFontsize < MIN_FONT_SIZE || iFontsize > MAX_FONT_SIZE);
  524.  
  525.     if (tFontRef == 0) {
  526.         l20 = draw_screenToDraw(32 + 3);
  527.     } else {
  528.         l20 = lWord2DrawUnits20(iFontsize);
  529.     }
  530.     pDiag->lYtop -= l20;
  531. } /* end of vMove2NextLine */
  532.  
  533. /*
  534.  * Create an end of paragraph by moving the y-high mark 1/3 line down
  535.  */
  536. void
  537. vEndOfParagraph2Diagram(diagram_type *pDiag,
  538.             draw_fontref tFontRef, int iFontsize)
  539. {
  540.     long    l20;
  541.  
  542.     fail(pDiag == NULL);
  543.     fail(iFontsize < MIN_FONT_SIZE || iFontsize > MAX_FONT_SIZE);
  544.  
  545.     if (tFontRef == 0) {
  546.         l20 = draw_screenToDraw(32 + 3);
  547.     } else {
  548.         l20 = lWord2DrawUnits20(iFontsize);
  549.     }
  550.     pDiag->lYtop -= l20 / 3;    /* Line spacing */
  551.     pDiag->lXleft = 0;
  552. } /* end of vEndOfParagraph2Diagram */
  553.  
  554. /*
  555.  * Create an end of page
  556.  */
  557. void
  558. vEndOfPage2Diagram(diagram_type *pDiag,
  559.             draw_fontref tFontRef, int iFontsize)
  560. {
  561.     vEndOfParagraph2Diagram(pDiag, tFontRef, iFontsize);
  562. } /* end of vEndOfPage2Diagram */
  563.  
  564. /*
  565.  * bVerifyDiagram - Verify the diagram generated from the Word file
  566.  *
  567.  * returns TRUE if the diagram is correct
  568.  */
  569. BOOL
  570. bVerifyDiagram(diagram_type *pDiag)
  571. {
  572.     draw_error    tError;
  573.  
  574.     fail(pDiag == NULL);
  575.     DBG_MSG("bVerifyDiagram");
  576.  
  577.     if (draw_verify_diag(&pDiag->tInfo, &tError)) {
  578.         return TRUE;
  579.     }
  580.     DBG_MSG("draw_verify_diag() failed");
  581.     vPrintDrawError(&tError);
  582.     return FALSE;
  583. } /* end of bVerifyDiagram */
  584.  
  585. void
  586. vShowDiagram(diagram_type *pDiag)
  587. {
  588.     wimp_wstate    tWindowState;
  589.     wimp_redrawstr    tRedraw;
  590.  
  591.     fail(pDiag == NULL);
  592.  
  593.     DBG_MSG("vShowDiagram");
  594.  
  595.     wimpt_noerr(wimp_get_wind_state(pDiag->tMainWindow, &tWindowState));
  596.     tWindowState.o.behind = -1;
  597.     wimpt_noerr(wimp_open_wind(&tWindowState.o));
  598.  
  599.     draw_queryBox(&pDiag->tInfo, (draw_box *)&tRedraw.box, TRUE);
  600.     tRedraw.w = pDiag->tMainWindow;
  601.     /* Work area extension */
  602.     tRedraw.box.x0 -= WORKAREA_EXTENSION;
  603.     tRedraw.box.y0 -= WORKAREA_EXTENSION;
  604.     tRedraw.box.x1 += WORKAREA_EXTENSION;
  605.     tRedraw.box.y1 += WORKAREA_EXTENSION;
  606.     wimpt_noerr(wimp_set_extent(&tRedraw));
  607. } /* end of vShowDiagram */
  608.  
  609. /*
  610.  * vMainButtonClick - handle mouse buttons clicks for the main screen
  611.  */
  612. static void
  613. vMainButtonClick(wimp_mousestr *m)
  614. {
  615.     wimp_caretstr    c;
  616.     wimp_wstate    ws;
  617.  
  618.     fail(m == NULL);
  619.  
  620.     NO_DBG_HEX(m->bbits);
  621.     NO_DBG_DEC(m->i);
  622.  
  623.     if (m->w >= 0 &&
  624.         m->i == -1 &&
  625.         ((m->bbits & wimp_BRIGHT) == wimp_BRIGHT ||
  626.          (m->bbits & wimp_BLEFT) == wimp_BLEFT)) {
  627.         /* Get the input focus */
  628.         wimpt_noerr(wimp_get_wind_state(m->w, &ws));
  629.         c.w = m->w;
  630.         c.i = -1;
  631.         c.x = m->x - ws.o.box.x0;
  632.         c.y = m->y - ws.o.box.y1;
  633.         c.height = (int)BIT(25);
  634.         c.index = 0;
  635.         wimpt_noerr(wimp_set_caret_pos(&c));
  636.     }
  637. } /* end of vMainButtonClick */
  638.  
  639. /*
  640.  * vMainKeyPressed - handle pressed keys for the main screen
  641.  */
  642. static void
  643. vMainKeyPressed(int chcode, wimp_caretstr *c, diagram_type *pDiag)
  644. {
  645.     fail(c == NULL || pDiag == NULL);
  646.     fail(c->w != pDiag->tMainWindow);
  647.  
  648.     switch (chcode) {
  649.     case akbd_Ctl+akbd_Fn+2:    /* Ctrl F2 */
  650.         vDestroyDiagram(c->w, pDiag);
  651.         break;
  652.     case akbd_Fn+3:            /* F3 */
  653.         vSaveDrawfile(pDiag);
  654.         break;
  655.     case akbd_Sh+akbd_Fn+3:        /* Shift F3 */
  656.         vSaveTextfile(pDiag);
  657.         break;
  658.     default:
  659.         DBG_DEC(chcode);
  660.         wimpt_noerr(wimp_processkey(chcode));
  661.     }
  662. } /* end of vMainKeyPressed */
  663.  
  664. /*
  665.  * vRedrawMainWindow - redraw the main window
  666.  */
  667. static void
  668. vRedrawMainWindow(wimp_w tWindow, diagram_type *pDiag)
  669. {
  670.     wimp_redrawstr    r;
  671.     draw_error    tError;
  672.     double        dScaleFactor;
  673.     draw_diag    *pInfo;
  674.     BOOL        bMore;
  675.  
  676.     fail(pDiag == NULL);
  677.     fail(pDiag->tMainWindow != tWindow);
  678.     fail(pDiag->iScaleFactorCurr < MIN_SCALE_FACTOR);
  679.     fail(pDiag->iScaleFactorCurr > MAX_SCALE_FACTOR);
  680.     fail(bDrawRenderDiag == NULL);
  681.  
  682.     dScaleFactor = (double)pDiag->iScaleFactorCurr / 100.0;
  683.     pInfo = &pDiag->tInfo;
  684.  
  685.     r.w = tWindow;
  686.     wimpt_noerr(wimp_redraw_wind(&r, &bMore));
  687.  
  688.     while (bMore) {
  689.         if (pInfo->data != NULL) {
  690.             if (!bDrawRenderDiag(pInfo,
  691.                     (draw_redrawstr *)&r,
  692.                     dScaleFactor,
  693.                     &tError)) {
  694.                 DBG_MSG("bDrawRenderDiag() failed");
  695.                 vPrintDrawError(&tError);
  696.             }
  697.         }
  698.         wimp_get_rectangle(&r, &bMore);
  699.     }
  700. } /* end of vRedrawMainWindow */
  701.  
  702. /*
  703.  * vMainEventHandler - event handler for the main screen
  704.  */
  705. void
  706. vMainEventHandler(wimp_eventstr *pEvent, void *pvHandle)
  707. {
  708.     diagram_type    *pDiag;
  709.  
  710.     fail(pEvent == NULL);
  711.  
  712.     pDiag = (diagram_type *)pvHandle;
  713.  
  714.     switch (pEvent->e) {
  715.     case wimp_ENULL:
  716.         break;
  717.     case wimp_EREDRAW:
  718.         vRedrawMainWindow(pEvent->data.o.w, pDiag);
  719.         break;
  720.     case wimp_EOPEN:
  721.         wimpt_noerr(wimp_open_wind(&pEvent->data.o));
  722.         break;
  723.     case wimp_ECLOSE:
  724.         vDestroyDiagram(pEvent->data.o.w, pDiag);
  725.         break;
  726.     case wimp_EBUT:
  727.         vMainButtonClick(&pEvent->data.but.m);
  728.         break;
  729.     case wimp_EKEY:
  730.         vMainKeyPressed(pEvent->data.key.chcode,
  731.                 &pEvent->data.key.c, pDiag);
  732.         break;
  733.     default:
  734.         break;
  735.     }
  736. } /* end of vMainEventHandler */
  737.  
  738. /*
  739.  * vScaleOpenAction - action to be taken when the Scale view window opens
  740.  */
  741. void
  742. vScaleOpenAction(diagram_type *pDiag)
  743. {
  744.     wimp_wstate    tWindowState;
  745.     wimp_mousestr    tMouseInfo;
  746.     int        iMoveX, iMoveY;
  747.  
  748.     fail(pDiag == NULL);
  749.  
  750.     wimpt_noerr(wimp_get_wind_state(pDiag->tScaleWindow, &tWindowState));
  751.     if ((tWindowState.flags & wimp_WOPEN) == wimp_WOPEN) {
  752.         /* The window is already open */
  753.         return;
  754.     }
  755.  
  756.     DBG_MSG("vScaleOpenAction");
  757.  
  758.     /* Allow the window to move in relation to the mouse position */
  759.     wimpt_noerr(wimp_get_point_info(&tMouseInfo));
  760.     iMoveX = tMouseInfo.x - tWindowState.o.box.x0 + 24;
  761.     iMoveY = tMouseInfo.y - tWindowState.o.box.y1 + 20;
  762.  
  763.     pDiag->iScaleFactorTemp = pDiag->iScaleFactorCurr;
  764.     vUpdateWriteableNumber(pDiag->tScaleWindow,
  765.             SCALE_SCALE_WRITEABLE, pDiag->iScaleFactorTemp);
  766.  
  767.     tWindowState.o.box.x0 += iMoveX;
  768.     tWindowState.o.box.x1 += iMoveX;
  769.     tWindowState.o.box.y0 += iMoveY;
  770.     tWindowState.o.box.y1 += iMoveY;
  771.     tWindowState.o.behind = -1;
  772.     wimpt_noerr(wimp_open_wind(&tWindowState.o));
  773. } /* end of vScaleOpenAction */
  774.  
  775. /*
  776.  * vSetTitle - set the title of a window
  777.  */
  778. void
  779. vSetTitle(diagram_type *pDiag)
  780. {
  781.     char    szTitle[WINDOW_TITLE_LEN];
  782.  
  783.     fail(pDiag == NULL);
  784.     fail(pDiag->szFilename[0] == '\0');
  785.  
  786.     (void)sprintf(szTitle, "%.*s at %d%%",
  787.                 FILENAME_TITLE_LEN,
  788.                 pDiag->szFilename,
  789.                 pDiag->iScaleFactorCurr % 1000);
  790.     if (strlen(pDiag->szFilename) > FILENAME_TITLE_LEN) {
  791.         szTitle[FILENAME_TITLE_LEN - 1] = OUR_ELLIPSIS;
  792.     }
  793.  
  794.     win_settitle(pDiag->tMainWindow, szTitle);
  795. } /* end of vSetTitle */
  796.  
  797. /*
  798.  * vForceRedraw - force a redraw of the main window
  799.  */
  800. static void
  801. vForceRedraw(diagram_type *pDiag)
  802. {
  803.     wimp_wstate    tWindowState;
  804.     wimp_redrawstr    tRedraw;
  805.  
  806.     DBG_MSG("vForceRedraw");
  807.  
  808.     fail(pDiag == NULL);
  809.  
  810.     DBG_DEC(pDiag->iScaleFactorCurr);
  811.  
  812.     /* Read the size of the current diagram */
  813.     draw_queryBox(&pDiag->tInfo, (draw_box *)&tRedraw.box, TRUE);
  814.     tRedraw.w = pDiag->tMainWindow;
  815.     /* Adjust the size of the work area */
  816.     tRedraw.box.x0 = tRedraw.box.x0 * pDiag->iScaleFactorCurr / 100 - 1;
  817.     tRedraw.box.y0 = tRedraw.box.y0 * pDiag->iScaleFactorCurr / 100 - 1;
  818.     tRedraw.box.x1 = tRedraw.box.x1 * pDiag->iScaleFactorCurr / 100 + 1;
  819.     tRedraw.box.y1 = tRedraw.box.y1 * pDiag->iScaleFactorCurr / 100 + 1;
  820.     /* Work area extension */
  821.     tRedraw.box.x0 -= WORKAREA_EXTENSION;
  822.     tRedraw.box.y0 -= WORKAREA_EXTENSION;
  823.     tRedraw.box.x1 += WORKAREA_EXTENSION;
  824.     tRedraw.box.y1 += WORKAREA_EXTENSION;
  825.     wimpt_noerr(wimp_set_extent(&tRedraw));
  826.     /* Widen the box slightly to be sure all the edges are drawn */
  827.     tRedraw.box.x0 -= 5;
  828.     tRedraw.box.y0 -= 5;
  829.     tRedraw.box.x1 += 5;
  830.     tRedraw.box.y1 += 5;
  831.     /* Force the redraw */
  832.     wimpt_noerr(wimp_force_redraw(&tRedraw));
  833.     /* Reopen the window to show the correct size */
  834.     wimpt_noerr(wimp_get_wind_state(pDiag->tMainWindow, &tWindowState));
  835.     tWindowState.o.behind = -1;
  836.     wimpt_noerr(wimp_open_wind(&tWindowState.o));
  837. } /* end of vForceRedraw */
  838.  
  839. /*
  840.  * vScaleButtonClick - handle a mouse button click in the Scale view window
  841.  */
  842. static void
  843. vScaleButtonClick(wimp_mousestr *m, diagram_type *pDiag)
  844. {
  845.     BOOL    bCloseWindow, bRedraw;
  846.  
  847.     fail(m == NULL || pDiag == NULL);
  848.     fail(m->w != pDiag->tScaleWindow);
  849.  
  850.     bCloseWindow = FALSE;
  851.     bRedraw = FALSE;
  852.     switch (m->i) {
  853.     case SCALE_CANCEL_BUTTON:
  854.         bCloseWindow = TRUE;
  855.         pDiag->iScaleFactorTemp = pDiag->iScaleFactorCurr;
  856.         break;
  857.     case SCALE_SCALE_BUTTON:
  858.         bCloseWindow = TRUE;
  859.         bRedraw = pDiag->iScaleFactorCurr != pDiag->iScaleFactorTemp;
  860.         pDiag->iScaleFactorCurr = pDiag->iScaleFactorTemp;
  861.         break;
  862.     case SCALE_50_PCT:
  863.         pDiag->iScaleFactorTemp = 50;
  864.         break;
  865.     case SCALE_75_PCT:
  866.         pDiag->iScaleFactorTemp = 75;
  867.         break;
  868.     case SCALE_100_PCT:
  869.         pDiag->iScaleFactorTemp = 100;
  870.         break;
  871.     case SCALE_150_PCT:
  872.         pDiag->iScaleFactorTemp = 150;
  873.         break;
  874.     default:
  875.         DBG_DEC(m->i);
  876.         break;
  877.     }
  878.     if (bCloseWindow) {
  879.         /* Close the scale window */
  880.         wimpt_noerr(wimp_close_wind(m->w));
  881.         if (bRedraw) {
  882.             /* Redraw the main window */
  883.             vSetTitle(pDiag);
  884.             vForceRedraw(pDiag);
  885.         }
  886.     } else {
  887.         vUpdateWriteableNumber(m->w,
  888.                 SCALE_SCALE_WRITEABLE,
  889.                 pDiag->iScaleFactorTemp);
  890.     }
  891. } /* end of vScaleButtonClick */
  892.  
  893. static void
  894. vScaleKeyPressed(int chcode, wimp_caretstr *c, diagram_type *pDiag)
  895. {
  896.     wimp_icon    tIcon;
  897.     char        *pcChar;
  898.     int        iTmp;
  899.  
  900.     DBG_MSG("vScaleKeyPressed");
  901.  
  902.     fail(c == NULL || pDiag == NULL);
  903.     fail(c->w != pDiag->tScaleWindow);
  904.  
  905.     DBG_DEC_C(c->i != SCALE_SCALE_WRITEABLE, c->i);
  906.     DBG_DEC_C(c->i == SCALE_SCALE_WRITEABLE, chcode);
  907.  
  908.     if (chcode != '\r' ||
  909.         c->w != pDiag->tScaleWindow ||
  910.         c->i != SCALE_SCALE_WRITEABLE) {
  911.         wimpt_noerr(wimp_processkey(chcode));
  912.         return;
  913.     }
  914.  
  915.     wimpt_noerr(wimp_get_icon_info(c->w, c->i, &tIcon));
  916.     if ((tIcon.flags & (wimp_ITEXT|wimp_INDIRECT)) !=
  917.         (wimp_ITEXT|wimp_INDIRECT)) {
  918.         werr(1, "Icon %d must be indirected text", (int)c->i);
  919.         return;
  920.     }
  921.     iTmp = (int)strtol(tIcon.data.indirecttext.buffer, &pcChar, 10);
  922.     if (*pcChar != '\0' && *pcChar != '\r') {
  923.         DBG_DEC(*pcChar);
  924.     } else if (iTmp < MIN_SCALE_FACTOR) {
  925.         pDiag->iScaleFactorTemp = MIN_SCALE_FACTOR;
  926.     } else if (iTmp > MAX_SCALE_FACTOR) {
  927.         pDiag->iScaleFactorTemp = MAX_SCALE_FACTOR;
  928.     } else {
  929.         pDiag->iScaleFactorTemp = iTmp;
  930.     }
  931.     pDiag->iScaleFactorCurr = pDiag->iScaleFactorTemp;
  932.     /* Close the scale window */
  933.     wimpt_noerr(wimp_close_wind(c->w));
  934.     /* Redraw the main window */
  935.     vSetTitle(pDiag);
  936.     vForceRedraw(pDiag);
  937. } /* end of vScaleKeyPressed */
  938.  
  939. /*
  940.  * vScaleEventHandler - event handler for the scale view screen
  941.  */
  942. void
  943. vScaleEventHandler(wimp_eventstr *pEvent, void *pvHandle)
  944. {
  945.     diagram_type    *pDiag;
  946.  
  947.     DBG_MSG("vScaleEventHandler");
  948.  
  949.     fail(pEvent == NULL);
  950.  
  951.     DBG_DEC(pEvent->e);
  952.  
  953.     pDiag = (diagram_type *)pvHandle;
  954.  
  955.     switch (pEvent->e) {
  956.     case wimp_ENULL:
  957.         break;
  958.     case wimp_EREDRAW:
  959.         /* handled by the WIMP */
  960.         break;
  961.     case wimp_EOPEN:
  962.         wimpt_noerr(wimp_open_wind(&pEvent->data.o));
  963.         break;
  964.     case wimp_ECLOSE:
  965.         wimpt_noerr(wimp_close_wind(pEvent->data.o.w));
  966.         break;
  967.     case wimp_EBUT:
  968.         vScaleButtonClick(&pEvent->data.but.m, pDiag);
  969.         break;
  970.     case wimp_EKEY:
  971.         vScaleKeyPressed(pEvent->data.key.chcode,
  972.                 &pEvent->data.key.c, pDiag);
  973.         break;
  974.     default:
  975.         break;
  976.     }
  977. } /* end of vScaleEventHandler */
  978.