home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / fontedit / fontchar.c < prev    next >
C/C++ Source or Header  |  1996-01-07  |  44KB  |  1,558 lines

  1. #include "windows.h"
  2. #include <windowsx.h>
  3. #include "fontedit.h"
  4. #include "fcntl.h"
  5. #include <stdio.h>
  6.  
  7. /****************************************************************************/
  8. /*              Shared Variables                                            */
  9. /****************************************************************************/
  10.  
  11. POINT SnapPointToGrid(POINT Pt);
  12. LONG  APIENTRY FontEditWndProc(HWND, WORD, WPARAM, LONG);
  13. BOOL  APIENTRY AboutDlg(
  14.     HWND   hDlg,
  15.     WORD   message,
  16.     WPARAM wParam,
  17.     LPARAM lParam
  18.     );
  19. BOOL   NewFile;                         /* flag indicating that NEW menu
  20.                                            item was selected */
  21. extern DLGPROC lpHeaderProc;            /* Pointer to Dialog Box Procedure */
  22. extern DLGPROC lpReSizeProc;            /* Pointer to Dialog Box Procedure */
  23. extern DLGPROC lpWidthProc;             /* Pointer to Dialog Box Procedure */
  24.  
  25. extern FontHeaderType font;             /* Structure of Font File Header */
  26. extern CHAR matBox [wBoxLim] [kBoxLim]; /* array to hold Box */
  27. extern HCURSOR hCross;                  /* handle to "+" shaped cursor(displayed
  28.                                            when in ROW or COLUMN menus */
  29. extern BOOL fReadOnly;
  30. extern HANDLE hInst;                    /* Module Handle */
  31. extern HBRUSH hbrBackGround;
  32. extern HWND hFont;
  33. extern HWND hBox;
  34. extern RECT rectWin;                    /* Client Rectangle */
  35. extern BOOL fLoaded;                    /* Set if a file loaded */
  36. extern BOOL fChanged;                   /* Anything has changed */
  37. extern BOOL fEdited;                    /* This character changed */
  38. extern DWORD kBox;                       /* height of character */
  39. extern DWORD wBox;                       /* Width of character */
  40. extern DWORD kStuff;                     /* Width of Show Header */
  41. extern INT  swH;                        /* Position in Show Window 0-100 */
  42. extern BYTE iChar;                      /* Character being edited */
  43. extern BYTE jChar;                      /* Last Char. of edit block */
  44. extern CHAR szNewFile[];                /* Name of New File */
  45. extern CHAR szFontFile[];               /* Name of Font File */
  46. extern CHAR szFontFileFull[];               /* Name of Font File */
  47. extern CHAR szFileNameTemp[];
  48. extern CHAR *szFileNameSave;
  49. extern INT cSysHeight;
  50.  
  51. extern CHAR *vrgsz[];                    /* total number of strings */
  52. extern OFSTRUCT ofstrFile;
  53. extern CHAR szExt[];                    /* default extension */
  54. extern CHAR szAppName[];
  55. extern CHAR szSCC[];
  56. extern HCURSOR hOldCursor;              /* handle to old arrow shaped cursor */
  57. /****************************************************************************/
  58. /*                      Local Variables                                     */
  59. /****************************************************************************/
  60.  
  61. HBRUSH hbrWhite;
  62. HBRUSH hbrBlack;
  63. HBRUSH hbrGray;
  64. HBRUSH hbrDkGray;
  65. HBRUSH hNullBrush;
  66. HPEN hWhitePen;
  67. DWORD colors[3] = {WHITENESS, BLACKNESS, PATCOPY};
  68.  
  69.  
  70. CHAR matBackup [wBoxLim] [kBoxLim];     /* Backup for UNDO */
  71. DWORD wBoxBackup;
  72.  
  73. LONG scale = 7;            /* height/width of squares in box */
  74. WORD cursor = 0;        /* Add/Del cursor */
  75.  
  76. BOOL fAll = TRUE;        /* Redraw all if TRUE */
  77. POINT ptBox = {10, 5};        /* where edit box is */
  78.  
  79. RECT    rectRubber;        /* Rubber banding rectangle */
  80. HDC    hDst;            /* Rubber banding dc */
  81.  
  82. POINT ptA;            /* Start of draw/rectangle */
  83. POINT ptB;            /* End of rectangle */
  84. POINT ptC;            /* Current square */
  85. CHAR colorA;            /* Color at/under point A */
  86. DWORD newWidth;            /* Width set in WIDER option */
  87. BOOL FillingRect = FALSE;
  88. BOOL fRubberBanding = FALSE;    /* flag indicating if rubberbanding in
  89.                                    progress for row/column add/delete */
  90. BOOL fStartRubberBand = FALSE;  /* flag indicating that rubberbanding
  91.                                    can start */
  92. BOOL fCaptured = FALSE;        /* set if mouse is caputred */
  93. BOOL fJustZapped = FALSE;    /* Set on row/col add/delete */
  94. RECT FontRect;            /* rectangle bounding font pattern */
  95.  
  96. /****************************************************************************/
  97. /*                      Local Functions                                     */
  98. /****************************************************************************/
  99.  
  100. VOID ClearFill(DWORD col, DWORD row, WORD mode);
  101. VOID FontEditCommand(HWND hBox, WORD id);
  102. VOID BoxRestore(VOID);
  103. VOID CharRectDimensions(LPRECT Rect);
  104. VOID BoxPaint(VOID);
  105. VOID DrawBox(HDC, DWORD, DWORD, DWORD, DWORD, INT, DWORD);
  106. VOID PASCAL DrawRubberBand(HDC hDst, LPRECT lpRect, DWORD rop);
  107. VOID FontEditPaint(HWND hBox, HDC hDC);
  108. BOOL CheckSave(VOID);
  109. VOID DupCol(DWORD col, DWORD row);
  110. VOID DupRow(DWORD col, DWORD row);
  111. VOID ZapCol(DWORD col, DWORD row);
  112. VOID ZapRow(DWORD col, DWORD row);
  113. VOID AddDel(DWORD col, DWORD row, WORD mode);
  114. VOID MouseInBox(HWND hBox, WORD message, POINT ptMouse);
  115. VOID BoxBackup(VOID);
  116. VOID ReadRect(VOID);
  117.  
  118. /*****************************************************************************/
  119. VOID
  120. BoxPaint(
  121.     VOID
  122.     )      /* Our call to FontEditPaint */
  123. {
  124.     HDC hDC;
  125.  
  126.     hDC = GetDC(hBox);
  127.     FontEditPaint(hBox,  hDC);
  128.     ReleaseDC(hBox, hDC);
  129.     if (fRubberBanding)
  130.         DrawRubberBand(hDst, &rectRubber, R2_XORPEN);
  131. }
  132.  
  133.  
  134. /******************************************************************************
  135.  * FontEditPaint(hBox, hDC)
  136.  *
  137.  * purpose: calculates coordinates for text in main window and repaints edit
  138.  *          box,small character boxes and text
  139.  *
  140.  * params:  HWND hBox : handle to main window
  141.  *          HDC hDC   I handle to display context
  142.  * returns: none
  143.  *
  144.  * side effects:  alters matBox (global 2-d array with ready pixel info. on
  145.  *                currently displayed box)
  146.  *****************************************************************************/
  147. VOID
  148. FontEditPaint(
  149.     HWND hBox,
  150.     HDC hDC
  151.     )
  152. {
  153.     CHAR szTemp[20];
  154.     DWORD len, yText, xText;
  155.  
  156.     if (!fLoaded)               /* Must load font first */
  157.         return;
  158.  
  159.     /* Here the application paints its window. */
  160.     if (fAll) {               /* Draw box setting */
  161.         GetClientRect(hBox, (LPRECT)&rectWin);
  162.         scale = (rectWin.bottom-rectWin.top-kStuff-20) / (kBox+1);
  163.         scale = min(scale, (min(320, rectWin.right - rectWin.left) - 
  164.                 90) / ((int)wBox + 1));
  165.         scale = max(scale, 4);
  166.         xText = ptBox.x + scale * wBox + 16;
  167.  
  168.         SelectObject(hDC, hbrDkGray);
  169.         Rectangle(hDC,
  170.             ptBox.x - 2,
  171.             ptBox.y - 2,
  172.             ptBox.x + 3 + wBox * scale,
  173.             ptBox.y + 5 + kBox * scale);
  174.         SelectObject(hDC, hbrGray);
  175.  
  176.         Rectangle(hDC,          /* Surround for font displays */
  177.             xText,
  178.             ptBox.y - 2,
  179.             xText + wBox + 8,
  180.             ptBox.y + 3 + kBox * 2 + font.ExtLeading);
  181.  
  182.         /* Now put up the text */
  183.         yText = 14 + 2 * kBox + font.ExtLeading;
  184.         len = (DWORD) sprintf(szTemp, vszCHAR, iChar);
  185.         TextOut(hDC, xText, yText, (LPSTR)szTemp, len);
  186.         len = (DWORD) sprintf(szTemp, vszWIDTH, wBox);
  187.         TextOut(hDC, xText, yText + cSysHeight, (LPSTR)szTemp, len);
  188.         len = (DWORD) sprintf(szTemp, vszHEIGHT, kBox);
  189.         TextOut(hDC, xText, yText + cSysHeight + cSysHeight, 
  190.             (LPSTR)szTemp, len);
  191.     }
  192.  
  193.     /* Draw Character Box */
  194.     DrawBox(hDC, ptBox.x, ptBox.y, wBox, kBox, scale, 1);
  195.  
  196.     /* Draw small character */
  197.     xText = ptBox.x + scale * wBox + 16;
  198.     DrawBox(hDC,
  199.         xText + 4,
  200.         ptBox.y,
  201.         wBox,
  202.         kBox,
  203.         1, 0);
  204.  
  205.     /* Draw another small character to show leading */
  206.     DrawBox(hDC,
  207.         xText + 4,
  208.         ptBox.y + kBox + font.ExtLeading,
  209.         wBox,
  210.         kBox,
  211.         1, 0);
  212.     fAll = TRUE;
  213. }
  214.  
  215.  
  216. /******************************************************************************
  217.  * DrawBox(hDC, xChar, yChar, wChar, kChar, scale, htSep)
  218.  *
  219.  * purpose: draws the edit box for the character being edited and colors the
  220.  *          grid squares according to the pixels set for the character.
  221.  *
  222.  * params:  HDC hDC         : handle to display context
  223.  *          DWORD xChar      : x-location of char box.
  224.  *          DWORD yChar      : y-location of char box
  225.  *          DWORD wChar      : width of char box
  226.  *          DWORD kChar      : height of char
  227.  *          INT   wScale     : Scale of the squares.
  228.  *          DWORD htSep      : height of square separators
  229.  *
  230.  * returns: none
  231.  *
  232.  * side effects:  alters matBox (global 2-d array with ready pixel info. on
  233.  *                currently displayed box)
  234.  *****************************************************************************/
  235. VOID
  236. DrawBox(
  237.     HDC hDC,
  238.     DWORD xChar,                             /* x-location of char. */
  239.     DWORD yChar,                             /* y-location of char. */
  240.     DWORD wChar,                             /* width of char. */
  241.     DWORD kChar,                             /* height of char */
  242.     INT   wScale,                 /* scale of the squares. */
  243.     DWORD htSep                              /* hgt of square separators */
  244.     )
  245. /* draw a character of separate squares of height 'scale' with sep. 'htSep' */
  246. {
  247.     DWORD i, j, sep;
  248.  
  249.     if (fAll) {               /* redraw them all */
  250.         for (j = 0; j < kChar; j++) {
  251.         sep = (j >= font.Ascent) ? htSep : 0;
  252.         for (i = 0; i < wChar; i++) {
  253.             if (wScale == 1)
  254.             SetPixel(hDC, xChar + i, yChar + j,
  255.                 matBox[i][j] == TRUE ? BLACK : WHITE);
  256.             else
  257.             PatBlt(hDC,
  258.                 xChar + wScale * i,
  259.                 yChar + wScale * j + sep,
  260.                 wScale - htSep,
  261.                 wScale - htSep,
  262.                 colors[matBox[i][j] == TRUE ? 1 : 0]);
  263.         }
  264.         }
  265.     }
  266.     else {            /* redraw one just flipped */
  267.         if (wScale == 1)
  268.         SetPixel(hDC,
  269.             xChar + ptC.x,
  270.             yChar + ptC.y,
  271.             matBox[ptC.x][ptC.y] == TRUE ? BLACK : WHITE);
  272.         else {
  273.         sep = (((DWORD) ptC.y >= font.Ascent) ? htSep : 0L);
  274.         SelectObject(hDC, hbrGray);
  275.         PatBlt(hDC,
  276.             xChar + wScale * ptC.x,
  277.             yChar + wScale * ptC.y + sep,
  278.             wScale - htSep,
  279.             wScale - htSep,
  280.             colors[matBox[ptC.x][ptC.y]]);
  281.         }
  282.     }
  283.  
  284. }
  285.  
  286.  
  287. /******************************************************************************
  288.  * FontEditCommand(hBox, id)
  289.  *
  290.  * purpose: interprets menu id and calls appropriate function to do the task
  291.  *
  292.  * params:  HWND hBox : handle to main window
  293.  *          WORD id   : menu command id
  294.  * returns: none
  295.  *
  296.  * side effects: plenty
  297.  *
  298.  *****************************************************************************/
  299. VOID
  300. FontEditCommand(
  301.     HWND hBox,
  302.     WORD id
  303.     )
  304. {
  305.     CHAR * szError;                 /* String for error messages */
  306.     LONG w; 
  307.     DWORD y, i, j;
  308.     BOOL fRepaint = FALSE;
  309.     HMENU hMenu;
  310.     DLGPROC lpprocAboutDlg;
  311.     MSG message;
  312.  
  313.     szError = "";               /* No Errors yet */
  314.  
  315.     switch (id) {
  316.         case FONT_EXIT:
  317.         if (!CheckSave())    /* See if any files need saving */
  318.             break;
  319.         /* Window's being destroyed. */
  320.         if (fLoaded)         /* 4/8/87 Linsh added */
  321.             DeleteGlobalBitmap(); /* Get rid of memory DC */
  322.         PostQuitMessage(0);  /* Cause application to be terminated */
  323.         break;
  324.  
  325.         case FONT_ABOUT:
  326.         lpprocAboutDlg = (DLGPROC)AboutDlg;
  327.         DialogBox (hInst, vszABOUT, hBox, lpprocAboutDlg);
  328.         FreeProcInstance (lpprocAboutDlg);
  329.         break;
  330.  
  331.         case FONT_LOAD:             /*  Check File Name  */
  332.         case FONT_NEW :
  333.         if (!CheckSave())       /*  See if current font needs saving */
  334.             return;
  335.     /* to prevent scrambling of Show window chars, Bring back Show
  336.         ** window to parent window's client area before invoking the dialog */
  337.  
  338.         if (CommDlgOpen(hBox,&ofstrFile,szNewFile,szExt,szFontFile,id)
  339.                 == FALSE) {
  340.  
  341.             InvalidateRect(hFont, (LPRECT)NULL, FALSE);
  342.             UpdateWindow(hFont);
  343.             return;
  344.         }
  345.         /* else drop thru */
  346.  
  347.         case FONT_START:    /*  Here if file name passed as argument */
  348.         InvalidateRect(hFont, (LPRECT)NULL, FALSE);
  349.         UpdateWindow(hFont);
  350.  
  351.         szError = FontLoad (szNewFile, &ofstrFile);
  352.  
  353.     /* Hack : needed to remove umwanted WM_MOUSEMOVE messages from the 
  354.          * queue.
  355.          * Apparently, Windows needs to reposition the mouse after a dialog
  356.          * is ended with a mouse double-click (releases mouse capture?) for
  357.          * which a couple of WM_MOUSEMOVEs may get sent to parent app.
  358.          * These mess with the edit box below the dialog if they happen to 
  359.          * overlap.
  360.          */
  361.         PeekMessage((LPMSG) &message, hBox, WM_MOUSEMOVE, WM_MOUSEMOVE,
  362.             PM_REMOVE);
  363.  
  364.         if (fLoaded)    /* If loaded then do a few things */ {
  365.             jChar = iChar = 65;                 /* Show an A */
  366.             if ((BYTE)iChar > (BYTE)font.LastChar)
  367.             jChar = iChar = font.FirstChar; /* .. if we can */
  368.             swH = 15;                   /* Good bet to make A visible */
  369.             fEdited = fChanged = FALSE;
  370.             ResizeShow();               /* Set Box to proper size */
  371.             ScrollFont();               /* Set thumb */
  372.             CharToBox(iChar);
  373.         }
  374.         FontRename(szError);
  375.         SetFocus(hBox);
  376.         return;
  377.  
  378.         case FONT_SAVE:
  379.         if (!NewFile) {
  380.             if (fLoaded && fChanged) {
  381.             lstrcpy((LPSTR)szNewFile, (LPSTR)szFontFileFull);
  382.             BoxToChar(iChar);           /* Just in case */
  383.             szError = FontSave (szNewFile, &ofstrFile);
  384.             FontRename(szError);        /* Rename or Print Error */
  385.             return;
  386.             }
  387.             else
  388.             return;
  389.         }
  390.     /* else file has been opened by selecting NEW... on menu.
  391.          * Fall thro' and bring up SaveAs dialog minus default
  392.          * filename in edit window */
  393.  
  394.         case FONT_SAVEAS:
  395.         BoxToChar(iChar);               /* Just in case */
  396.  
  397.         if (CommDlgSaveAs (hInst, hBox, &ofstrFile, szNewFile, szExt,
  398.                 szFontFile) == TRUE) {
  399.  
  400.             szError = FontSave (szNewFile, &ofstrFile);
  401.             FontRename (szError);          /* Rename or Print Error */
  402.         }
  403.  
  404.         /* to prevent scrambling of Show window chars,
  405.            repaint show window after dialog is brought down */
  406.         InvalidateRect (hFont, (LPRECT)NULL, TRUE);
  407.         UpdateWindow (hFont);
  408.         return;
  409.  
  410.         case FONT_HEADER:
  411.         /* to prevent scrambling of Show window chars,
  412.          * repaint show window after dialog is invoked */
  413.         DialogBox(hInst, (LPSTR)vszDHeader, hBox, lpHeaderProc);
  414.         InvalidateRect(hFont, (LPRECT)NULL, TRUE);
  415.         UpdateWindow(hFont);
  416.         return;
  417.  
  418.         case FONT_RESIZE:
  419.         /* to prevent scrambling of Show window chars,
  420.            repaint show window after dialog is brought down */
  421.         if (DialogBox(hInst, (LPSTR)vszDResize, hBox, lpReSizeProc)) {
  422.             /* BoxToChar(iChar);*/ /* save current before resizing */
  423.             ResizeShow();       /* New Font Display Size */
  424.             CharToBox(iChar);               /* New Box display */
  425.         }
  426.         InvalidateRect(hFont, (LPRECT)NULL, TRUE);
  427.         UpdateWindow(hFont);
  428.         return;
  429.  
  430.         case FONT_COPY:                     /* Copy to Clipboard */
  431.         BoxToChar(iChar);               /* Just in case */
  432.         ToClipboard(iChar, wBox, kBox);
  433.         break;
  434.  
  435.         case FONT_PASTE:            /* Paste in Character form Clipboard */
  436.         BoxBackup();            /* In case we change our minds */
  437.         ptA.x = ptA.y = 0;
  438.         wBox = ClipboardToBox(ptA, wBox, kBox, TRUE);
  439.         fRepaint = TRUE;
  440.         break;
  441.  
  442.         case WIDER_LEFT:
  443.         case WIDER_RIGHT:
  444.         case WIDER_BOTH:
  445.         case NARROWER_LEFT:
  446.         case NARROWER_RIGHT:
  447.         case NARROWER_BOTH:
  448.         case WIDTH:
  449.         w = newWidth = wBox;
  450.         if (font.Family & 1)            /* Variable width or else */ {
  451.             switch (id) {
  452.             case WIDER_BOTH:
  453.                 w++;
  454.             case WIDER_LEFT:
  455.             case WIDER_RIGHT:
  456.                 w++;
  457.                 break;
  458.             case NARROWER_BOTH:
  459.                 w--;
  460.             case NARROWER_LEFT:
  461.             case NARROWER_RIGHT:
  462.                 w--;
  463.                 break;
  464.             case WIDTH:
  465.                 if (DialogBox(hInst,
  466.                     (LPSTR)vszDWidth, hBox, lpWidthProc))
  467.                 w = newWidth;
  468.                 break;
  469.             }
  470.  
  471.             if (w < 0 || w >= wBoxLim) {
  472.             MessageBox(hBox,
  473.                 (LPSTR)vszEdLimits0To64,
  474.                 (LPSTR)szAppName,
  475.                 MB_OK | MB_ICONASTERISK);
  476.             break;                  /* Out of range! quit */
  477.             }
  478.             if (w > (LONG) font.MaxWidth) {
  479.             if (IDOK == MessageBox(hBox,
  480.                         (LPSTR)vszMaxWidthIncrease,
  481.                         (LPSTR)szAppName,
  482.                         MB_OKCANCEL | MB_ICONQUESTION))
  483.                 font.MaxWidth = (WORD)w;
  484.             else
  485.                 break;
  486.             }
  487.             BoxBackup();                /* In case we change our minds */
  488.             wBox = (WORD)w;             /* Reset width */
  489.             fRepaint = TRUE;            /* Signal redraw */
  490.             switch (id) {
  491.             case WIDER_LEFT:
  492.             DupCol(0, kBoxLim - 1);
  493.             for (y = 0; y < kBoxLim; y++)
  494.                 matBox[0][y] = FALSE;       /* Clear left column */
  495.             break;
  496.             case WIDER_BOTH:            /* Shift character one right */
  497.             DupCol(0, kBoxLim - 1);
  498.             for (y = 0; y < kBoxLim; y++)
  499.                 matBox[wBox -1][y] = FALSE; /* Clear right column */
  500.             for (y = 0; y < kBoxLim; y++)
  501.                 matBox[0][y] = FALSE;       /* Clear left column */
  502.             break;
  503.             case NARROWER_LEFT:
  504.             case NARROWER_BOTH:    /* Shift character one left */
  505.             if (wBox) {    /* .. unless width is already 0 */
  506.                 for (j = 0; j <= kBox - 1; j++)
  507.                 for (i = 0; i <= wBox - 1; i++)
  508.                     matBox[i][j] = matBox[i + 1][j];
  509.                 break;
  510.             }
  511.             }
  512.         }
  513.         else {
  514.             MessageBox(hBox,
  515.                 (LPSTR)vszCannotChangeWidth,
  516.                 (LPSTR)szAppName,
  517.                 MB_OK | MB_ICONASTERISK);
  518.         }
  519.         break;
  520.  
  521.         case ROW_ADD:
  522.         case ROW_DEL:
  523.         case COL_ADD:
  524.         case COL_DEL:
  525.         /* set cursor to "+" shaped cursor */
  526.         SetCapture (hBox); /* so that cursor doesn't get restored
  527.                       before we are done */
  528.         hOldCursor = SetCursor (LoadCursor (NULL, IDC_CROSS));
  529.         fCaptured = TRUE;
  530.         cursor = id;
  531.         break;
  532.  
  533.         case BOX_CLEAR:
  534.         case BOX_FILL:
  535.         case BOX_INV:
  536.         case BOX_HATCH:
  537.         case BOX_LEFTRIGHT:
  538.         case BOX_TOPBOTTOM:
  539.         case BOX_COPY:
  540.         case BOX_PASTE:
  541.         /* Get one o' da funky cursors */
  542.         SetCapture(hBox);
  543.         hOldCursor = SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(id)));
  544.         fStartRubberBand = TRUE;
  545.         CharRectDimensions((LPRECT)&FontRect);
  546.         cursor = id;
  547.         break;
  548.  
  549.         case BOX_REFRESH:           /* Go get old version of character */
  550.         BoxBackup();            /* In case we change our minds */
  551.         CharToBox(iChar);
  552.         hMenu = GetMenu(hBox);
  553.         EnableMenuItem(hMenu, BOX_UNDO, MF_ENABLED);    /* Can Unrefresh! */
  554.         break;
  555.         case BOX_UNDO:
  556.         BoxRestore();
  557.         hMenu = GetMenu(hBox);
  558.         EnableMenuItem(hMenu, BOX_REFRESH, MF_ENABLED);
  559.         fRepaint = TRUE;
  560.         break;
  561.     }
  562.     if (fRepaint) {
  563.         fEdited = fChanged = TRUE;
  564.         InvalidateRect(hBox, (LPRECT)NULL, TRUE);
  565.     }
  566. }
  567.  
  568.  
  569. VOID
  570. CharRectDimensions(
  571.     LPRECT Rect
  572.     )
  573. /* returns the dimensions of the edit box */
  574. {
  575.     Rect->top    =  ptBox.y;
  576.     Rect->bottom =  ptBox.y + (kBox) * (scale);
  577.     Rect->left   =  ptBox.x;
  578.     Rect->right  =  ptBox.x + (wBox) * (scale);
  579. }
  580.  
  581.  
  582. /******************************************************************************
  583.  * BOOL  APIENTRY WidthProc(hDial, message, wParam, lParam)
  584.  *
  585.  * purpose: dialog function for Width menu function
  586.  *
  587.  * params:  same as for all dialog fns.
  588.  *
  589.  * side effects: changes Box width variable
  590.  *
  591.  *****************************************************************************/
  592. BOOL  APIENTRY 
  593. WidthProc(
  594.     HWND   hDial,
  595.     WORD   message,
  596.     WPARAM wParam,
  597.     LPARAM lParam
  598.     )
  599. {
  600.     INT i;
  601.     BOOL fOk;
  602.  
  603.     UNREFERENCED_PARAMETER(lParam);
  604.  
  605.     switch (message) {
  606.     default:
  607.         return FALSE;
  608.     case WM_INITDIALOG:
  609.         SetDlgItemInt(hDial, BOX_WIDTH, newWidth, FALSE);
  610.         break;
  611.  
  612.     case WM_COMMAND:
  613.         switch (LOWORD(wParam)) {
  614.         case IDOK:
  615.             fChanged = TRUE;
  616.             i = GetDlgItemInt(hDial, BOX_WIDTH, (LPBOOL)&fOk, FALSE);
  617.             if (fOk && i < wBoxLim)
  618.                 newWidth = i;
  619.             else
  620.                 ErrorBox(hDial, vszWidthOutOfBounds);
  621.  
  622.         case IDCANCEL:
  623.             EndDialog(hDial, LOWORD(wParam) != IDCANCEL);
  624.             break;
  625.  
  626.         default:
  627.             break;
  628.         }
  629.     }
  630.     return TRUE;
  631. }
  632.  
  633.  
  634. /******************************************************************************
  635.  * BOOL CheckSave()
  636.  *
  637.  * purpose: checks if font is dirty and prompts user to save font. If yes,
  638.  *          edit box is saved and file save function is called.
  639.  *
  640.  * params:  none
  641.  *
  642.  * returns: TRUE : font has been changed
  643.  *          FALSE: font untouched
  644.  *
  645.  * side effects: file dirty flag is reset.
  646.  *
  647.  *****************************************************************************/
  648. BOOL 
  649. CheckSave(
  650.     VOID
  651.     )
  652. {
  653.     CHAR * szError;                 /* String for error messages */
  654.     CHAR szMessage[MAX_STR_LEN+MAX_FNAME_LEN];
  655.  
  656.     /* Check if anything changed */
  657.     if (fLoaded && fChanged && (!fReadOnly)) {
  658.         lstrcpy((LPSTR)szNewFile, (LPSTR)szFontFileFull);
  659.         DlgMergeStrings(szSCC, szNewFile, szMessage);
  660.         switch (MessageBox(hFont,
  661.             (LPSTR)szMessage,
  662.             (LPSTR)szAppName,
  663.             MB_YESNOCANCEL | MB_ICONQUESTION)) {
  664.         case IDYES:
  665.             BoxToChar(iChar);            /* Just in case */
  666.             szError = FontSave (szNewFile, &ofstrFile);
  667.             FontRename(szError);            /* Rename or Print Error */
  668.         case IDNO:
  669.             return TRUE;
  670.         case IDCANCEL:
  671.             return FALSE;
  672.         }
  673.     }
  674.     return TRUE;
  675. }
  676.  
  677.  
  678. /******************************************************************************
  679.  * MouseInBox(hBox, message, ptMouse)
  680.  *
  681.  * purpose: do edit operation depending on currently active menu command
  682.  *
  683.  * params: HWND hBox       : handle to main window
  684.  *         WORD message    : Message retrieved by main window's window fn.
  685.  *         POINT ptMouse   : current mouse coordinates
  686.  * returns: none
  687.  *
  688.  * side effects: alters matBox (global 2-d array with ready pixel info. on
  689.  *               currently displayed box). Also assigns values to ptA and ptB
  690.  *****************************************************************************/
  691. VOID
  692. MouseInBox(
  693.     HWND hBox,
  694.     WORD message,
  695.     POINT ptMouse
  696.     )
  697. {
  698.     POINT pt;
  699.     BOOL fRepaint = FALSE;
  700.     short nct = 0 ;
  701.  
  702.     pt = SnapPointToGrid(ptMouse);
  703.  
  704.     if (pt.x >= 0L && pt.y >= 0L &&
  705.         ((DWORD)pt.x) < wBox && ((DWORD)pt.y) < kBox) {
  706.         fEdited = fChanged = TRUE;
  707.         ptC.x = pt.x;
  708.         ptC.y = pt.y;            /* Current square */
  709.         if (message == WM_LBUTTONDOWN)
  710.             BoxBackup();        /* Set up for UNDO */
  711.         switch (cursor) {
  712.         case BOX_COPY:
  713.         case BOX_PASTE:
  714.         case BOX_CLEAR:
  715.         case BOX_FILL:
  716.         case BOX_INV:
  717.         case BOX_HATCH:
  718.         case BOX_LEFTRIGHT:
  719.         case BOX_TOPBOTTOM:
  720.             ptA.x = pt.x;
  721.             ptA.y = pt.y;        /* save anchor point */
  722.                         /* save color under marker */
  723.             colorA = matBox[pt.x][pt.y];
  724.             fAll = FALSE;
  725.  
  726.             fRepaint = TRUE;
  727.             break;
  728.         default:
  729.             AddDel(pt.x, pt.y, cursor);
  730.             fRepaint = TRUE;
  731.             cursor = FALSE;
  732.             break;
  733.         case FALSE:
  734.             switch (message) {
  735.             case WM_LBUTTONDOWN:    /*invert */
  736.                 nct =1 ;
  737.                 colorA = (matBox[pt.x][pt.y] ^= TRUE);
  738.                 break;
  739.  
  740.             case WM_LBUTTONUP:
  741.                 break;
  742.  
  743.             case WM_MOUSEMOVE:
  744.                 matBox[pt.x][pt.y] = colorA;    /* paint */
  745.                 break;
  746.             }
  747. /*
  748.             if( nct != 0 )
  749.             {
  750. */
  751.             fRepaint = TRUE;
  752.             fAll = FALSE;               /* Limited redraw */
  753. /*
  754.             }
  755. */
  756.             break;
  757.         }
  758.         if (fRepaint) {
  759.             BoxPaint();
  760.             return;
  761.         }
  762.     }
  763.     cursor = FALSE;
  764. }
  765.  
  766.  
  767. /******************************************************************************
  768.  * ReadRect(ptMouse)
  769.  *
  770.  * purpose:      defines the rectangular region in edit box to be filled by
  771.  *               fill menu command  by fixing top left (ptA) and bottom right
  772.  *               (ptB) coordinates of rect.
  773.  *
  774.  * params:
  775.  *
  776.  * assumes:    that rectRubber is normalized (eg, left < right, botton > top)
  777.  *
  778.  * returns:    none
  779.  *
  780.  * side effects: alters matBox (global 2-d array with ready pixel info. on
  781.  *               currently displayed box). Also assigns values to ptA and ptB
  782.  *****************************************************************************/
  783. VOID
  784. ReadRect(
  785.     )
  786. {
  787.  
  788.     ptA.x = (rectRubber.left-(ptBox.x+1))   / scale;
  789.     ptA.y = (rectRubber.top-(ptBox.y+1))    / scale;
  790.     ptB.x = (rectRubber.right-(ptBox.x-2))  / scale - 1;
  791.     ptB.y = (rectRubber.bottom-(ptBox.y-2)) / scale - 1;
  792.  
  793.     if (((DWORD)ptB.x) > wBox - 1)
  794.         ptB.x = wBox - 1;
  795.     if (((DWORD)ptB.y) > kBox - 1)
  796.         ptB.y = kBox - 1;
  797.  
  798.     if (ptB.x >= 0 && ptB.y >= 0) {
  799.         ClearFill((DWORD)ptB.x, (DWORD)ptB.y, cursor);        
  800.         BoxPaint();
  801.     }
  802.     cursor = FALSE;
  803. }
  804.  
  805.  
  806. /******************************************************************************
  807.  * ClearFill(col, row, mode)
  808.  *
  809.  * purpose:  fill the specified rectangular region in edit box with fill type
  810.  *           indicated by mode.Top left corner of rect is global(ptA)
  811.  *
  812.  * params:   DWORD row : row (of bottom right corner of rect(ptB.x))
  813.  *           DWORD col : column (of bottom right corner of rect(ptB.y))
  814.  *           WORD mode: action to be performed
  815.  *
  816.  * returns:  none
  817.  *
  818.  * side effects: alters matBox (global 2-d array with ready pixel info. on
  819.  *               currently displayed box)
  820.  *****************************************************************************/
  821. VOID
  822. ClearFill(
  823.     DWORD col, 
  824.     DWORD row, 
  825.     WORD mode
  826.     )
  827. {
  828.     DWORD i, x, y;
  829.     CHAR z;
  830.  
  831.     if (col < (DWORD)ptA.x) /* if points are reversed */ {
  832.         i = col;
  833.         col = ptA.x;
  834.         ptA.x = i;
  835.     }          /* flip them */
  836.     if (row < (DWORD) ptA.y) {
  837.         i = row;
  838.         row = ptA.y;
  839.         ptA.y = i;
  840.     }          /* flip them */
  841.  
  842.     if (mode == BOX_LEFTRIGHT) {
  843.         for (x = ptA.x; x <= (DWORD)((ptA.x + col) / 2); x++)
  844.             for (y = ptA.y; y <= row; y++) {
  845.                 z = matBox[x][y];
  846.                 matBox[x][y] = matBox[ptA.x + col - x][y];
  847.                 matBox[ptA.x + col - x][y] = z;
  848.             }
  849.         return;
  850.     }
  851.  
  852.     if (mode == BOX_TOPBOTTOM) {
  853.         for (y = ptA.y; y <= ((DWORD)(ptA.y + row) / 2); y++)
  854.             for (x = ptA.x; x <= col; x++) {
  855.                 z = matBox[x][y];
  856.                 matBox[x][y] = matBox[x][ptA.y + row - y];
  857.                 matBox[x][ptA.y + row - y] = z;
  858.             }
  859.         return;
  860.     }
  861.  
  862.     if (mode == BOX_COPY)
  863.         BoxToClipboard(ptA, col - ptA.x + 1, row - ptA.y + 1);
  864.  
  865.     if (mode == BOX_PASTE)
  866.         ClipboardToBox(ptA, col - ptA.x + 1, row - ptA.y + 1, FALSE);
  867.  
  868.     for (x = ptA.x; x <= col; x++)
  869.         for (y = ptA.y; y <= row; y++) {
  870.             switch (mode) {
  871.             case BOX_CLEAR:
  872.             case BOX_FILL:
  873.                 matBox[x][y] = (CHAR)(mode == BOX_FILL);
  874.                 break;
  875.             case BOX_INV:
  876.                 matBox[x][y] ^= (CHAR)TRUE;
  877.                 break;
  878.             case BOX_HATCH:
  879.                 matBox[x][y] = (CHAR)((x+y)%2 ? TRUE : FALSE);
  880.                 break;
  881.             }
  882.         }
  883. }
  884.  
  885.  
  886. /******************************************************************************
  887.  * AddDel(col, row, mode)
  888.  *
  889.  * purpose:  Add/Delete row/col as per mode
  890.  *
  891.  * params:   DWORD row : row
  892.  *           DWORD col : column
  893.  *           WORD mode: action to be performed
  894.  *
  895.  * returns:  none
  896.  *
  897.  * side effects: alters matBox (global 2-d array with ready pixel info. on
  898.  *               currently displayed box)
  899.  *****************************************************************************/
  900. VOID
  901. AddDel(
  902.     DWORD col, 
  903.     DWORD row, 
  904.     WORD mode
  905.     )
  906. {
  907.     switch (mode) {
  908.     case ROW_ADD:
  909.         DupRow(wBox, row);
  910.         break;
  911.  
  912.     case ROW_DEL:
  913.         ZapRow(wBox, row);
  914.         break;
  915.  
  916.     case COL_ADD:
  917.         DupCol(col, kBox);
  918.         break;
  919.  
  920.     case COL_DEL:
  921.         ZapCol(col, kBox);
  922.         break;
  923.     }
  924.     /* restore arrow cursor */
  925.     SetCursor (hOldCursor);
  926.     ReleaseCapture();
  927.     fCaptured = FALSE;
  928.     fJustZapped = TRUE;
  929. }
  930.  
  931.  
  932. /******************************************************************************
  933.  * ZapCol(col, row)
  934.  *
  935.  * purpose: delete given column in edit box. Shift cols to right given col
  936.  *          right. Rightmost column gets duplicated.
  937.  *
  938.  * params : DWORD col : column
  939.  *          DWORD row : row
  940.  * returns: none
  941.  *
  942.  * side effects: alters matBox (global 2-d array with ready pixel info. on
  943.  *               currently displayed box)
  944.  *****************************************************************************/
  945. VOID
  946. ZapCol(
  947.     DWORD col, 
  948.     DWORD row
  949.     )
  950. {
  951.     DWORD x, y;
  952.     for (y = 0; y <= row; y++)
  953.         for (x = col; x < wBox - 1; x++)
  954.             matBox[x][y] = matBox[x + 1][y];
  955.     for (y = 0; y <= row; y++)
  956.         matBox[x][y] = matBox[x - 1][y];
  957. }
  958.  
  959.  
  960. /******************************************************************************
  961.  * ZapRow(col, row)
  962.  *
  963.  * purpose: delete given row in edit box. Shift rows below given row up. Lowest
  964.  *          row gets duplicated
  965.  *
  966.  * params:  DWORD col : column
  967.  *          DWORD row : row
  968.  * returns: none
  969.  *
  970.  * side effects: alters matBox (global 2-d array with ready pixel info. on
  971.  *               currently displayed box)
  972.  *****************************************************************************/
  973. VOID
  974. ZapRow(
  975.     DWORD col, 
  976.     DWORD row
  977.     )
  978. {
  979.     DWORD x, y;
  980.     for (x = 0; x <= col; x++)
  981.         for (y = row; y < kBox - 1; y++)
  982.             matBox[x][y] = matBox[x][y + 1];
  983.     for (x = 0; x <= col; x++)
  984.         matBox[x][y] = matBox[x][y - 1];
  985. }
  986.  
  987.  
  988. /******************************************************************************
  989.  * DupCol(col, row)
  990.  *
  991.  * purpose: duplicate given column in edit box. Shift cols to right of given
  992.  *          col right
  993.  *
  994.  * params:  DWORD col : column
  995.  *          DWORD row : row
  996.  * returns: none
  997.  *
  998.  * side effects: alters matBox (global 2-d array with ready pixel info. on
  999.  *               currently displayed box)
  1000.  *****************************************************************************/
  1001. VOID
  1002. DupCol(
  1003.     DWORD col, 
  1004.     DWORD row
  1005.     )
  1006. {
  1007.     DWORD x, y;
  1008.     for (x = wBox - 1; x > col; x--)
  1009.         for (y = 0; y <= row; y++)
  1010.             matBox[x][y] = matBox[x - 1][y];
  1011. }
  1012.  
  1013.  
  1014. /******************************************************************************
  1015.  * DupRow(col, row)
  1016.  *
  1017.  * purpose: duplicate given row in edit box. Shift rows below given row down.
  1018.  *
  1019.  * params:  DWORD col : column
  1020.  *          DWORD row : row
  1021.  * returns: none
  1022.  *
  1023.  * side effects: alters matBox (global 2-d array with ready pixel info. on
  1024.  *               currently displayed box)
  1025.  *****************************************************************************/
  1026. VOID
  1027. DupRow(
  1028.     DWORD col, 
  1029.     DWORD row
  1030.     )
  1031. {
  1032.     DWORD x, y;
  1033.     for (x = 0; x <= col; x++)
  1034.         for (y = kBox - 1; y > row; y--)
  1035.             matBox[x][y] = matBox[x][y - 1];
  1036. }
  1037.  
  1038.  
  1039. /******************************************************************************
  1040.  * ClearBox(col, row, bb)
  1041.  *
  1042.  * purpose: reset all pixels in edit box (make box white)
  1043.  *
  1044.  * params : none
  1045.  *
  1046.  * returns: none
  1047.  *
  1048.  * side effects: alters matBox (global 2-d array with ready pixel info. on
  1049.  *               currently displayed box)
  1050.  *
  1051.  *****************************************************************************/
  1052. VOID
  1053. ClearBox(
  1054.     VOID
  1055.     )                  /* Clear edit box */
  1056. {
  1057.     DWORD x, y;
  1058.     for (x = 0; x < wBoxLim; x++)
  1059.         for (y = 0; y < kBoxLim; y++)
  1060.             matBox[x][y] = FALSE;
  1061. }
  1062.  
  1063.  
  1064. /******************************************************************************
  1065.  * BoxBackup()
  1066.  *
  1067.  * purpose:   makes a backup of pix. info. of currently displayed edit box
  1068.  *
  1069.  * params:    none
  1070.  *
  1071.  * returns:   none
  1072.  *
  1073.  * side effects: alters matBackup (local 2-d array with backup pixel info.
  1074.  *               on edit box )
  1075.  *****************************************************************************/
  1076. VOID
  1077. BoxBackup(
  1078.     VOID
  1079.     )
  1080. {
  1081.     DWORD x, y;
  1082.     HMENU hMenu;
  1083.  
  1084.     hMenu = GetMenu(hBox);
  1085.     EnableMenuItem(hMenu, BOX_UNDO, MF_ENABLED);
  1086.     EnableMenuItem(hMenu, BOX_REFRESH, MF_ENABLED);
  1087.     for (x = 0; x < wBoxLim; x++)
  1088.         for (y = 0; y < kBoxLim; y++)
  1089.             matBackup[x][y] = matBox[x][y];
  1090.     wBoxBackup = wBox;
  1091. }
  1092.  
  1093.  
  1094. /******************************************************************************
  1095.  * BoxRestore()
  1096.  *
  1097.  * purpose : Current edit box and backup box exchange places
  1098.  *
  1099.  * params  : none
  1100.  *
  1101.  * returns : none
  1102.  *
  1103.  * side effects: alters matBox (global 2-d array with ready pixel info. on
  1104.  *               currently displayed box
  1105.  *
  1106.  *****************************************************************************/
  1107. VOID
  1108. BoxRestore(
  1109.     VOID
  1110.     )            /* Box and Backup exchange places */
  1111. {
  1112.     DWORD x, y, temp;
  1113.     CHAR z;
  1114.  
  1115.     for (x = 0; x < wBoxLim; x++)
  1116.         for (y = 0; y < kBoxLim; y++) {
  1117.             z = matBackup[x][y];
  1118.             matBackup[x][y] = matBox[x][y];
  1119.             matBox[x][y] = z;
  1120.         }
  1121.     temp = wBox;
  1122.     wBox = wBoxBackup;
  1123.     wBoxBackup = temp;
  1124. }
  1125.  
  1126.  
  1127. /******************************************************************************
  1128.  * POINT SnapPointToGrid (Pt)
  1129.  *
  1130.  * purpose : Intended only for the Fill menu command where rubberbanding rect.
  1131.  *           needs to be aligned on the grid lines. Snap the current mouse
  1132.  *           coordinates to nearest grid intersection.
  1133.  *
  1134.  * params  : POINT Pt : current point mouse is over
  1135.  *
  1136.  * returns : POINT    : number of nearest square
  1137.  *
  1138.  * side effects:      : current mouse coordinate(global variable) altered to
  1139.  *                      return value
  1140.  *
  1141.  *****************************************************************************/
  1142. POINT 
  1143. SnapPointToGrid(
  1144.     POINT    Pt
  1145.     )
  1146. {
  1147.  
  1148.     Pt.x = (Pt.x - ptBox.x) / scale;
  1149.     if (Pt.y > (scale * (font.Ascent - 1)))
  1150.         Pt.y = Pt.y - 2;    /* Allow for break in box */
  1151.     Pt.y = (Pt.y - ptBox.y) / scale;
  1152.     return (Pt);
  1153. }
  1154.  
  1155.  
  1156. /******************************************************************************
  1157.  * VOID PASCAL EndRubberBandingRect()
  1158.  *
  1159.  * purpose: Stops rubberbanding rect for Fill menu command and cleans up
  1160.  *
  1161.  * params : HANDLE hDst : handle to dest. DC
  1162.  *
  1163.  * side effects: none
  1164.  *
  1165.  *****************************************************************************/
  1166. VOID PASCAL 
  1167. EndRubberBandingRect(
  1168.     HDC hDst  /* handle to dest. DC */
  1169.     )
  1170. {
  1171.     fRubberBanding = FALSE;      /* reset "in-progress" flag */
  1172.  
  1173.     ReleaseDC(hBox, hDst);
  1174.     ReleaseCapture();
  1175.     SetCursor(hOldCursor);
  1176. }
  1177.  
  1178.  
  1179. /******************************************************************************
  1180.  * HDC PASCAL InitialiseRubberBandingRect(hBox)
  1181.  *
  1182.  * purpose: Sets up rubberbanding rect for Fill menu command.
  1183.  *
  1184.  * params : HANDLE hDst : handle to box DC
  1185.  *
  1186.  * returns :handle to destination display context
  1187.  *
  1188.  * side effects: alters few global flags for rubberbanding
  1189.  *
  1190.  *****************************************************************************/
  1191. HDC PASCAL 
  1192. InitialiseRubberBandingRect(
  1193.     HDC hBox  /* handle to  DC  of box */
  1194.     )
  1195. {
  1196.     HDC hDst;
  1197.  
  1198.     fRubberBanding = TRUE;       /* set "in-progress" flag */
  1199.     fStartRubberBand = FALSE;    /* reset "start-proceedings" flag */
  1200.     SetCapture(hBox);            /* send all msgs to current window */
  1201.  
  1202.     hDst = GetDC (hBox);
  1203.  
  1204.     /* select pen and fill mode for rectangle*/
  1205.     hWhitePen  = SelectObject(hDst, GetStockObject (WHITE_PEN));
  1206.     hNullBrush = SelectObject(hDst, GetStockObject (NULL_BRUSH));
  1207.     SetROP2(hDst, R2_XORPEN);
  1208.  
  1209.     return(hDst);
  1210. }
  1211.  
  1212.  
  1213. /******************************************************************************
  1214.  * VOID PASCAL DrawRubberBand()
  1215.  *
  1216.  * purpose: Draw rubberbanding rect for Fill menu command.
  1217.  *
  1218.  * params : HANDLE hDst : handle to dest. DC
  1219.  *
  1220.  * side effects: alters few global flags for rubberbanding
  1221.  *
  1222.  *****************************************************************************/
  1223. VOID PASCAL 
  1224. DrawRubberBand(
  1225.     HDC       hDst,                        /*  handle to dest. DC */
  1226.     LPRECT    lpRect,
  1227.     DWORD    rop
  1228.     )
  1229. {
  1230. #ifdef DBG
  1231.     char    buf[256];
  1232.         SIZE        Size;
  1233.         static LONG cxPrev;
  1234.         INT         nLeftRect;
  1235. #endif
  1236.  
  1237.     SetROP2(hDst, rop);
  1238.     Rectangle(hDst, lpRect->left,  lpRect->top,
  1239.             lpRect->right, lpRect->bottom);
  1240.  
  1241. #ifdef DBG
  1242.     sprintf(buf, "left=%d, top=%d, right=%d, bottom=%d", 
  1243.         lpRect->left,  lpRect->top, lpRect->right, lpRect->bottom);
  1244.     GetTextExtentPoint32(hDst, buf, lstrlen(buf), &Size);
  1245.     nLeftRect = ptBox.x+scale*wBox+16 + Size.cx;
  1246.     if(nLeftRect < cxPrev) {
  1247.         RECT rc;
  1248.         rc.left   = nLeftRect;
  1249.         rc.top    = 14+2*kBox+font.ExtLeading+3*cSysHeight;
  1250.         rc.right  = cxPrev;
  1251.         rc.bottom = 14+2*kBox+font.ExtLeading+3*cSysHeight + Size.cy;
  1252.         FillRect(hDst, &rc, hbrBackGround);
  1253.     }
  1254.     cxPrev = nLeftRect;
  1255.     TextOut(hDst, ptBox.x+scale*wBox+16,
  1256.               14+2*kBox+font.ExtLeading+3*cSysHeight,
  1257.               buf, strlen(buf));
  1258. #endif
  1259. }
  1260.  
  1261.  
  1262. /******************************************************************************
  1263.  * long  APIENTRY FontEditWndProc(hBox, message, wParam, lParam)
  1264.  *
  1265.  * purpose: Master controller for Fontedit's all-encompassing main window
  1266.  *
  1267.  * params : same as for all window functions
  1268.  *
  1269.  * side effects: countless
  1270.  *
  1271.  *****************************************************************************/
  1272. LONG  APIENTRY 
  1273. FontEditWndProc(
  1274.     HWND   hBox,
  1275.     WORD   message,
  1276.     WPARAM wParam,
  1277.     LPARAM lParam
  1278.     )
  1279. {
  1280.     PAINTSTRUCT    ps;
  1281.     HMENU    hMenu;
  1282.     WORD    mf;
  1283.     POINT    pt;
  1284.     RECT    BoxRect;
  1285.  
  1286.     switch (message) {
  1287.     case WM_CLOSE:
  1288.         if (!CheckSave())    /* See if any files need saving */
  1289.             break;
  1290.         /* Window's being destroyed. */
  1291.         if (fLoaded)         /* 4/8/87 Linsh added */
  1292.             DeleteGlobalBitmap(); /* Get rid of memory DC */
  1293.         DestroyWindow(hFont);
  1294.         DestroyWindow(hBox);
  1295.         break;
  1296.  
  1297.     case WM_DESTROY:
  1298.         PostQuitMessage(0);  /* Cause application to be terminated */
  1299.         break;
  1300.  
  1301.     case WM_QUERYENDSESSION:
  1302.         if (CheckSave())             /* See if any files need saving */
  1303.             return TRUE;
  1304.         break;
  1305.  
  1306.     case WM_ENDSESSION:
  1307.         if (fLoaded)
  1308.             DeleteGlobalBitmap();      /* Get rid of memory DC */
  1309.         break;
  1310.  
  1311.     case WM_SIZE:
  1312.         /* Window's size is changing.  lParam contains the width
  1313.         ** and height, in the low and high words, respectively.
  1314.         ** wParam contains SIZENORMAL for "normal" size changes,
  1315.         ** SIZEICONIC when the window is being made iconic, and
  1316.         ** SIZEFULLSCREEN when the window is being made full screen. */
  1317.         switch (wParam) {
  1318.         case SIZEFULLSCREEN:
  1319.         case SIZENORMAL:
  1320.             ResizeShow();
  1321.             if (kStuff != GetkStuff())    /* Did it change ? */
  1322.                 ResizeShow();           /* Yes resize again */
  1323.             break;
  1324.         }
  1325.         break;
  1326.  
  1327.     case WM_MOVE: /* Tell popup to move with us. */
  1328.         if (!IsIconic(hBox))
  1329.             ResizeShow();
  1330.         break;
  1331.  
  1332.     case WM_PAINT:
  1333.         /* Time for the window to draw itself. */
  1334.         BeginPaint(hBox, (LPPAINTSTRUCT)&ps);
  1335.         FontEditPaint(hBox,  ps.hdc);
  1336.         EndPaint(hBox, (LPPAINTSTRUCT)&ps);
  1337.         break;
  1338.  
  1339.  
  1340.     case WM_COMMAND:
  1341.         /* A menu item has been selected, or a control is notifying
  1342.          * its parent.  wParam is the menu item value (for menus),
  1343.          * or control ID (for controls).  For controls, the low word
  1344.          * of lParam has the window handle of the control, and the hi
  1345.          * word has the notification code.  For menus, lParam contains
  1346.          * 0L. */
  1347.         FontEditCommand(hBox, LOWORD(wParam));
  1348.         break;
  1349.  
  1350.         /* Data interchange request. */
  1351.     case WM_CUT:
  1352.     case WM_COPY:
  1353.     case WM_PASTE:
  1354.     case WM_CLEAR:
  1355.     case WM_UNDO:
  1356.     case WM_RENDERFORMAT:
  1357.     case WM_RENDERALLFORMATS:
  1358.     case WM_DESTROYCLIPBOARD:
  1359.     case WM_DRAWCLIPBOARD:
  1360.         break;
  1361.     case WM_INITMENU:
  1362.         hMenu = GetMenu(hBox);  /* Gray menu if no clipboard bitmap */
  1363.         mf = (WORD)(IsClipboardFormatAvailable(CF_BITMAP) ? MF_ENABLED : 
  1364.                 MF_GRAYED);
  1365.         EnableMenuItem(hMenu, BOX_PASTE, mf);
  1366.         EnableMenuItem(hMenu, FONT_PASTE, mf);
  1367.         break;
  1368.  
  1369.     /* For each of following mouse window messages, wParam contains
  1370.     ** bits indicating whether or not various virtual keys are down,
  1371.     ** and lParam is a POINT containing the mouse coordinates.   The
  1372.     ** keydown bits of wParam are:  MK_LBUTTON (set if Left Button is
  1373.     ** down); MK_RBUTTON (set if Right Button is down); MK_SHIFT (set
  1374.     ** if Shift Key is down); MK_ALTERNATE (set if Alt Key is down);
  1375.     ** and MK_CONTROL (set if Control Key is down). */
  1376.  
  1377.     case WM_LBUTTONDOWN:
  1378.         ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y);
  1379.  
  1380.         if (fStartRubberBand) {
  1381.             /* a green signal to rubberband a rectangle for the
  1382.              * Fill menu command rectangle now has null dimensions.
  1383.              * Snap the current mouse point to nearest grid
  1384.              * intersection thus defining upper left corner of
  1385.              * rectangle */
  1386.  
  1387.             if (PtInRect((LPRECT)&FontRect, pt)) {
  1388.                 pt = SnapPointToGrid(pt);
  1389.                 rectRubber.top    =  pt.y   *scale+ptBox.y+1;
  1390.                 rectRubber.bottom = (pt.y+1)*scale+ptBox.y-2;
  1391.                 rectRubber.left   =  pt.x   *scale+ptBox.x+1;
  1392.                 rectRubber.right  = (pt.x+1)*scale+ptBox.x-2;
  1393.  
  1394.                 hDst = InitialiseRubberBandingRect(hBox);
  1395.                 DrawRubberBand(hDst, &rectRubber, R2_XORPEN);
  1396.             }
  1397.             else {
  1398.                 fStartRubberBand = fRubberBanding = FALSE;
  1399.                 ReleaseCapture();
  1400.             }
  1401.         }
  1402.         /* do operation depending upon current active command,
  1403.          * but not if we just added/deleted a row/column. */
  1404.         if (!fJustZapped) {
  1405.             if (fStartRubberBand) {
  1406.                 pt.x *= scale;
  1407.                 pt.y *= scale;
  1408.                 MouseInBox(hBox, message, pt);
  1409.             }
  1410.             else {
  1411.                 ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y);
  1412.                 MouseInBox(hBox, message, pt);
  1413.             }
  1414.         }
  1415.  
  1416.         break;
  1417.  
  1418.     case WM_LBUTTONUP:               /* Get other corner of rectangle */
  1419.         fJustZapped = FALSE;
  1420.         if (fRubberBanding) {
  1421.             /* if rubberbanding for the Fill menu command,
  1422.              * terminate proceedings and clean up */
  1423.             DrawRubberBand(hDst, &rectRubber, R2_NOT);
  1424.             EndRubberBandingRect(hDst);
  1425.             if (cursor) {
  1426.                 ReadRect();
  1427.             }
  1428.         }
  1429.         if (fCaptured ) {
  1430.             /* if cursor is + shaped, restore it to default */
  1431.             ReleaseCapture();
  1432.             SetCursor (hOldCursor);
  1433.         }
  1434.         break;
  1435.  
  1436.     case WM_RBUTTONDOWN:
  1437.     case WM_RBUTTONUP:
  1438.         break;
  1439.  
  1440.     case WM_MOUSEMOVE:                      /* If mouse is down */
  1441.  
  1442.         ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y);
  1443.  
  1444.         if ((fRubberBanding) && (wParam & MK_LBUTTON)) {
  1445.             /* if any of Fill menu commands is active
  1446.             ** (AND the mouse key depressed) draw a rubberband
  1447.             ** a rectangle with the mouse movements */
  1448.  
  1449.             /* get current square number */
  1450.             pt = SnapPointToGrid(pt);
  1451.  
  1452.             /* calculate grid for new square */
  1453.             BoxRect.top    =  pt.y   *scale+ptBox.y+1;
  1454.             BoxRect.bottom = (pt.y+1)*scale+ptBox.y-2;
  1455.             BoxRect.left   =  pt.x   *scale+ptBox.x+1;
  1456.             BoxRect.right  = (pt.x+1)*scale+ptBox.x-2;
  1457.  
  1458.             /* erase old mark */
  1459.             DrawRubberBand(hDst, &rectRubber, R2_NOT);
  1460.  
  1461.             /* limit rubber band to box */
  1462.             if (BoxRect.right > (LONG) (scale * wBox + ptBox.x))
  1463.                 BoxRect.right = scale * wBox + ptBox.x;
  1464.             if (BoxRect.bottom > (LONG) (scale * kBox + ptBox.y))
  1465.                 BoxRect.bottom = scale * kBox + ptBox.y;
  1466.             if (BoxRect.top < 0)
  1467.                 BoxRect.top = 1;
  1468.             if (BoxRect.left < 0)
  1469.                 BoxRect.left = 1;
  1470.  
  1471.             if (ptA.x == pt.x) {
  1472.                 rectRubber.right  = BoxRect.right;
  1473.                 rectRubber.left   = BoxRect.left;
  1474.             }
  1475.             if (ptA.y == pt.y) {
  1476.                 rectRubber.bottom = BoxRect.bottom;
  1477.                 rectRubber.top    = BoxRect.top;
  1478.             }
  1479.  
  1480.             /* almost an IntersectRect */
  1481.             if (ptA.x >= pt.x)
  1482.                 rectRubber.left   = BoxRect.left;
  1483.             else
  1484.                 rectRubber.right  = BoxRect.right;
  1485.  
  1486.             if (ptA.y >= pt.y)
  1487.                 rectRubber.top    = BoxRect.top;
  1488.             else
  1489.                 rectRubber.bottom = BoxRect.bottom;
  1490.  
  1491.             /* Draw new mark */
  1492.             DrawRubberBand(hDst, &rectRubber, R2_XORPEN);
  1493.         }
  1494.         else {
  1495.             /* if not "Fill"ing(AND mouse key depressed,
  1496.              * paint with the mouse movements */
  1497.             if ((wParam & MK_LBUTTON) && cursor == FALSE && 
  1498.                 fJustZapped == FALSE)
  1499.                 MouseInBox(hBox, message, pt);
  1500.         }
  1501.         break;
  1502.  
  1503.     case WM_LBUTTONDBLCLK:
  1504.     case WM_RBUTTONDBLCLK:
  1505.         break;
  1506.  
  1507.     default:
  1508.  
  1509.         /* Everything else comes here.  This call MUST exist
  1510.         ** in your window proc.  */
  1511.  
  1512.         return(DefWindowProc(hBox, message, wParam, lParam));
  1513.         break;
  1514.     }
  1515.  
  1516.     /* A window proc should always return something */
  1517.     return(0L);
  1518. }
  1519.  
  1520.  
  1521. /***************************** Public  Function ****************************\
  1522. *
  1523. * BOOL  APIENTRY AboutDlg(hDlg, message, wParam, lParam)
  1524. * HWND     hDlg;
  1525. * WORD message;
  1526. * WPARAM wParam;
  1527. * LPARAM lParam;
  1528. *
  1529. *
  1530. * Effects: none.
  1531. *
  1532. \***************************************************************************/
  1533. BOOL  APIENTRY 
  1534. AboutDlg(
  1535.     HWND   hDlg,
  1536.     WORD   message,
  1537.     WPARAM wParam,
  1538.     LPARAM lParam
  1539.     )
  1540. {
  1541.     UNREFERENCED_PARAMETER(lParam);
  1542.  
  1543.     switch (message) {
  1544.     case WM_INITDIALOG:
  1545.         break;
  1546.  
  1547.     case WM_COMMAND:
  1548.         EndDialog(hDlg, LOWORD(wParam));
  1549.         /* idok or idcancel */
  1550.         break;
  1551.  
  1552.     default:
  1553.         return FALSE;
  1554.         break;
  1555.     }
  1556.     return(TRUE);
  1557. }
  1558.