FONTCHAR.C
#include "windows.h" 
#include <windowsx.h> 
#include "fontedit.h" 
#include "fcntl.h" 
#include <stdio.h> 
 
/****************************************************************************/ 
/*              Shared Variables                                            */ 
/****************************************************************************/ 
 
POINT SnapPointToGrid(POINT Pt); 
LONG  APIENTRY FontEditWndProc(HWND, WORD, WPARAM, LONG); 
BOOL  APIENTRY AboutDlg( 
HWND   hDlg, 
WORD   message, 
WPARAM wParam, 
LPARAM lParam 
); 
BOOL   NewFile;                         /* flag indicating that NEW menu 
                                           item was selected */ 
extern DLGPROC lpHeaderProc;            /* Pointer to Dialog Box Procedure */ 
extern DLGPROC lpReSizeProc;            /* Pointer to Dialog Box Procedure */ 
extern DLGPROC lpWidthProc;             /* Pointer to Dialog Box Procedure */ 
 
extern FontHeaderType font;             /* Structure of Font File Header */ 
extern CHAR matBox [wBoxLim] [kBoxLim]; /* array to hold Box */ 
extern HCURSOR hCross;                  /* handle to "+" shaped cursor(displayed 
                                           when in ROW or COLUMN menus */ 
extern BOOL fReadOnly; 
extern HANDLE hInst;                    /* Module Handle */ 
extern HBRUSH hbrBackGround; 
extern HWND hFont; 
extern HWND hBox; 
extern RECT rectWin;                    /* Client Rectangle */ 
extern BOOL fLoaded;                    /* Set if a file loaded */ 
extern BOOL fChanged;                   /* Anything has changed */ 
extern BOOL fEdited;                    /* This character changed */ 
extern DWORD kBox;                       /* height of character */ 
extern DWORD wBox;                       /* Width of character */ 
extern DWORD kStuff;                     /* Width of Show Header */ 
extern INT  swH;                        /* Position in Show Window 0-100 */ 
extern BYTE iChar;                      /* Character being edited */ 
extern BYTE jChar;                      /* Last Char. of edit block */ 
extern CHAR szNewFile[];                /* Name of New File */ 
extern CHAR szFontFile[];               /* Name of Font File */ 
extern CHAR szFontFileFull[];               /* Name of Font File */ 
extern CHAR szFileNameTemp[]; 
extern CHAR *szFileNameSave; 
extern INT cSysHeight; 
 
extern CHAR *vrgsz[];                    /* total number of strings */ 
extern OFSTRUCT ofstrFile; 
extern CHAR szExt[];                    /* default extension */ 
extern CHAR szAppName[]; 
extern CHAR szSCC[]; 
extern HCURSOR hOldCursor;              /* handle to old arrow shaped cursor */ 
/****************************************************************************/ 
/*                      Local Variables                                     */ 
/****************************************************************************/ 
 
HBRUSH hbrWhite; 
HBRUSH hbrBlack; 
HBRUSH hbrGray; 
HBRUSH hbrDkGray; 
HBRUSH hNullBrush; 
HPEN hWhitePen; 
DWORD colors[3] = {WHITENESS, BLACKNESS, PATCOPY}; 
 
 
CHAR matBackup [wBoxLim] [kBoxLim];     /* Backup for UNDO */ 
DWORD wBoxBackup; 
 
LONG scale = 7;/* height/width of squares in box */ 
WORD cursor = 0;/* Add/Del cursor */ 
 
BOOL fAll = TRUE;/* Redraw all if TRUE */ 
POINT ptBox = {10, 5};/* where edit box is */ 
 
RECTrectRubber;/* Rubber banding rectangle */ 
HDChDst;/* Rubber banding dc */ 
 
POINT ptA;/* Start of draw/rectangle */ 
POINT ptB;/* End of rectangle */ 
POINT ptC;/* Current square */ 
CHAR colorA;/* Color at/under point A */ 
DWORD newWidth;/* Width set in WIDER option */ 
BOOL FillingRect = FALSE; 
BOOL fRubberBanding = FALSE;/* flag indicating if rubberbanding in 
                                   progress for row/column add/delete */ 
BOOL fStartRubberBand = FALSE;  /* flag indicating that rubberbanding 
                                   can start */ 
BOOL fCaptured = FALSE;/* set if mouse is caputred */ 
BOOL fJustZapped = FALSE;/* Set on row/col add/delete */ 
RECT FontRect;/* rectangle bounding font pattern */ 
 
/****************************************************************************/ 
/*                      Local Functions                                     */ 
/****************************************************************************/ 
 
VOID ClearFill(DWORD col, DWORD row, WORD mode); 
VOID FontEditCommand(HWND hBox, WORD id); 
VOID BoxRestore(VOID); 
VOID CharRectDimensions(LPRECT Rect); 
VOID BoxPaint(VOID); 
VOID DrawBox(HDC, DWORD, DWORD, DWORD, DWORD, INT, DWORD); 
VOID PASCAL DrawRubberBand(HDC hDst, LPRECT lpRect, DWORD rop); 
VOID FontEditPaint(HWND hBox, HDC hDC); 
BOOL CheckSave(VOID); 
VOID DupCol(DWORD col, DWORD row); 
VOID DupRow(DWORD col, DWORD row); 
VOID ZapCol(DWORD col, DWORD row); 
VOID ZapRow(DWORD col, DWORD row); 
VOID AddDel(DWORD col, DWORD row, WORD mode); 
VOID MouseInBox(HWND hBox, WORD message, POINT ptMouse); 
VOID BoxBackup(VOID); 
VOID ReadRect(VOID); 
 
/*****************************************************************************/ 
VOID 
BoxPaint( 
VOID 
)      /* Our call to FontEditPaint */ 
{ 
HDC hDC; 
 
hDC = GetDC(hBox); 
FontEditPaint(hBox,  hDC); 
ReleaseDC(hBox, hDC); 
if (fRubberBanding) 
DrawRubberBand(hDst, &rectRubber, R2_XORPEN); 
} 
 
 
/****************************************************************************** 
 * FontEditPaint(hBox, hDC) 
 * 
 * purpose: calculates coordinates for text in main window and repaints edit 
 *          box,small character boxes and text 
 * 
 * params:  HWND hBox : handle to main window 
 *          HDC hDC   I handle to display context 
 * returns: none 
 * 
 * side effects:  alters matBox (global 2-d array with ready pixel info. on 
 *                currently displayed box) 
 *****************************************************************************/ 
VOID 
FontEditPaint( 
HWND hBox, 
HDC hDC 
) 
{ 
CHAR szTemp[20]; 
DWORD len, yText, xText; 
 
if (!fLoaded)               /* Must load font first */ 
return; 
 
/* Here the application paints its window. */ 
if (fAll) {               /* Draw box setting */ 
GetClientRect(hBox, (LPRECT)&rectWin); 
scale = (rectWin.bottom-rectWin.top-kStuff-20) / (kBox+1); 
scale = min(scale, (min(320, rectWin.right - rectWin.left) -  
90) / ((int)wBox + 1)); 
scale = max(scale, 4); 
xText = ptBox.x + scale * wBox + 16; 
 
SelectObject(hDC, hbrDkGray); 
Rectangle(hDC, 
    ptBox.x - 2, 
    ptBox.y - 2, 
    ptBox.x + 3 + wBox * scale, 
    ptBox.y + 5 + kBox * scale); 
SelectObject(hDC, hbrGray); 
 
Rectangle(hDC,          /* Surround for font displays */ 
    xText, 
    ptBox.y - 2, 
    xText + wBox + 8, 
    ptBox.y + 3 + kBox * 2 + font.ExtLeading); 
 
/* Now put up the text */ 
yText = 14 + 2 * kBox + font.ExtLeading; 
len = (DWORD) sprintf(szTemp, vszCHAR, iChar); 
TextOut(hDC, xText, yText, (LPSTR)szTemp, len); 
len = (DWORD) sprintf(szTemp, vszWIDTH, wBox); 
TextOut(hDC, xText, yText + cSysHeight, (LPSTR)szTemp, len); 
len = (DWORD) sprintf(szTemp, vszHEIGHT, kBox); 
TextOut(hDC, xText, yText + cSysHeight + cSysHeight,  
(LPSTR)szTemp, len); 
} 
 
/* Draw Character Box */ 
DrawBox(hDC, ptBox.x, ptBox.y, wBox, kBox, scale, 1); 
 
/* Draw small character */ 
xText = ptBox.x + scale * wBox + 16; 
DrawBox(hDC, 
    xText + 4, 
    ptBox.y, 
    wBox, 
    kBox, 
    1, 0); 
 
/* Draw another small character to show leading */ 
DrawBox(hDC, 
    xText + 4, 
    ptBox.y + kBox + font.ExtLeading, 
    wBox, 
    kBox, 
    1, 0); 
fAll = TRUE; 
} 
 
 
/****************************************************************************** 
 * DrawBox(hDC, xChar, yChar, wChar, kChar, scale, htSep) 
 * 
 * purpose: draws the edit box for the character being edited and colors the 
 *          grid squares according to the pixels set for the character. 
 * 
 * params:  HDC hDC         : handle to display context 
 *          DWORD xChar      : x-location of char box. 
 *          DWORD yChar      : y-location of char box 
 *          DWORD wChar      : width of char box 
 *          DWORD kChar      : height of char 
 *          INT   wScale     : Scale of the squares. 
 *          DWORD htSep      : height of square separators 
 * 
 * returns: none 
 * 
 * side effects:  alters matBox (global 2-d array with ready pixel info. on 
 *                currently displayed box) 
 *****************************************************************************/ 
VOID 
DrawBox( 
HDC hDC, 
DWORD xChar,                             /* x-location of char. */ 
DWORD yChar,                             /* y-location of char. */ 
DWORD wChar,                             /* width of char. */ 
DWORD kChar,                             /* height of char */ 
INT   wScale, /* scale of the squares. */ 
DWORD htSep                              /* hgt of square separators */ 
) 
/* draw a character of separate squares of height 'scale' with sep. 'htSep' */ 
{ 
DWORD i, j, sep; 
 
if (fAll) {               /* redraw them all */ 
    for (j = 0; j < kChar; j++) { 
sep = (j >= font.Ascent) ? htSep : 0; 
for (i = 0; i < wChar; i++) { 
    if (wScale == 1) 
SetPixel(hDC, xChar + i, yChar + j, 
matBox[i][j] == TRUE ? BLACK : WHITE); 
    else 
PatBlt(hDC, 
xChar + wScale * i, 
yChar + wScale * j + sep, 
wScale - htSep, 
wScale - htSep, 
colors[matBox[i][j] == TRUE ? 1 : 0]); 
} 
    } 
} 
else {/* redraw one just flipped */ 
    if (wScale == 1) 
SetPixel(hDC, 
xChar + ptC.x, 
yChar + ptC.y, 
matBox[ptC.x][ptC.y] == TRUE ? BLACK : WHITE); 
    else { 
sep = (((DWORD) ptC.y >= font.Ascent) ? htSep : 0L); 
SelectObject(hDC, hbrGray); 
PatBlt(hDC, 
xChar + wScale * ptC.x, 
yChar + wScale * ptC.y + sep, 
wScale - htSep, 
wScale - htSep, 
colors[matBox[ptC.x][ptC.y]]); 
    } 
} 
 
} 
 
 
/****************************************************************************** 
 * FontEditCommand(hBox, id) 
 * 
 * purpose: interprets menu id and calls appropriate function to do the task 
 * 
 * params:  HWND hBox : handle to main window 
 *          WORD id   : menu command id 
 * returns: none 
 * 
 * side effects: plenty 
 * 
 *****************************************************************************/ 
VOID 
FontEditCommand( 
HWND hBox, 
WORD id 
) 
{ 
CHAR * szError;                 /* String for error messages */ 
LONG w;  
DWORD y, i, j; 
BOOL fRepaint = FALSE; 
HMENU hMenu; 
DLGPROC lpprocAboutDlg; 
MSG message; 
 
szError = "";               /* No Errors yet */ 
 
switch (id) { 
    case FONT_EXIT: 
if (!CheckSave())    /* See if any files need saving */ 
break; 
/* Window's being destroyed. */ 
if (fLoaded)         /* 4/8/87 Linsh added */ 
DeleteGlobalBitmap(); /* Get rid of memory DC */ 
PostQuitMessage(0);  /* Cause application to be terminated */ 
break; 
 
    case FONT_ABOUT: 
lpprocAboutDlg = (DLGPROC)AboutDlg; 
DialogBox (hInst, vszABOUT, hBox, lpprocAboutDlg); 
FreeProcInstance (lpprocAboutDlg); 
break; 
 
    case FONT_LOAD:             /*  Check File Name  */ 
    case FONT_NEW : 
if (!CheckSave())       /*  See if current font needs saving */ 
return; 
/* to prevent scrambling of Show window chars, Bring back Show 
        ** window to parent window's client area before invoking the dialog */ 
 
if (CommDlgOpen(hBox,&ofstrFile,szNewFile,szExt,szFontFile,id) 
== FALSE) { 
 
InvalidateRect(hFont, (LPRECT)NULL, FALSE); 
UpdateWindow(hFont); 
return; 
} 
/* else drop thru */ 
 
    case FONT_START:/*  Here if file name passed as argument */ 
InvalidateRect(hFont, (LPRECT)NULL, FALSE); 
UpdateWindow(hFont); 
 
szError = FontLoad (szNewFile, &ofstrFile); 
 
/* Hack : needed to remove umwanted WM_MOUSEMOVE messages from the  
         * queue. 
         * Apparently, Windows needs to reposition the mouse after a dialog 
         * is ended with a mouse double-click (releases mouse capture?) for 
         * which a couple of WM_MOUSEMOVEs may get sent to parent app. 
         * These mess with the edit box below the dialog if they happen to  
         * overlap. 
         */ 
PeekMessage((LPMSG) &message, hBox, WM_MOUSEMOVE, WM_MOUSEMOVE, 
    PM_REMOVE); 
 
if (fLoaded)    /* If loaded then do a few things */ { 
    jChar = iChar = 65;                 /* Show an A */ 
    if ((BYTE)iChar > (BYTE)font.LastChar) 
jChar = iChar = font.FirstChar; /* .. if we can */ 
    swH = 15;                   /* Good bet to make A visible */ 
    fEdited = fChanged = FALSE; 
    ResizeShow();               /* Set Box to proper size */ 
    ScrollFont();               /* Set thumb */ 
    CharToBox(iChar); 
} 
FontRename(szError); 
SetFocus(hBox); 
return; 
 
    case FONT_SAVE: 
if (!NewFile) { 
    if (fLoaded && fChanged) { 
lstrcpy((LPSTR)szNewFile, (LPSTR)szFontFileFull); 
BoxToChar(iChar);           /* Just in case */ 
szError = FontSave (szNewFile, &ofstrFile); 
FontRename(szError);        /* Rename or Print Error */ 
return; 
    } 
    else 
return; 
} 
/* else file has been opened by selecting NEW... on menu. 
         * Fall thro' and bring up SaveAs dialog minus default 
         * filename in edit window */ 
 
    case FONT_SAVEAS: 
BoxToChar(iChar);               /* Just in case */ 
 
if (CommDlgSaveAs (hInst, hBox, &ofstrFile, szNewFile, szExt, 
szFontFile) == TRUE) { 
 
    szError = FontSave (szNewFile, &ofstrFile); 
    FontRename (szError);          /* Rename or Print Error */ 
} 
 
/* to prevent scrambling of Show window chars, 
           repaint show window after dialog is brought down */ 
InvalidateRect (hFont, (LPRECT)NULL, TRUE); 
UpdateWindow (hFont); 
return; 
 
    case FONT_HEADER: 
/* to prevent scrambling of Show window chars, 
 * repaint show window after dialog is invoked */ 
DialogBox(hInst, (LPSTR)vszDHeader, hBox, lpHeaderProc); 
InvalidateRect(hFont, (LPRECT)NULL, TRUE); 
UpdateWindow(hFont); 
return; 
 
    case FONT_RESIZE: 
/* to prevent scrambling of Show window chars, 
   repaint show window after dialog is brought down */ 
if (DialogBox(hInst, (LPSTR)vszDResize, hBox, lpReSizeProc)) { 
    /* BoxToChar(iChar);*/ /* save current before resizing */ 
    ResizeShow();       /* New Font Display Size */ 
    CharToBox(iChar);               /* New Box display */ 
} 
InvalidateRect(hFont, (LPRECT)NULL, TRUE); 
UpdateWindow(hFont); 
return; 
 
    case FONT_COPY:                     /* Copy to Clipboard */ 
BoxToChar(iChar);               /* Just in case */ 
ToClipboard(iChar, wBox, kBox); 
break; 
 
    case FONT_PASTE:            /* Paste in Character form Clipboard */ 
BoxBackup();            /* In case we change our minds */ 
ptA.x = ptA.y = 0; 
wBox = ClipboardToBox(ptA, wBox, kBox, TRUE); 
fRepaint = TRUE; 
break; 
 
    case WIDER_LEFT: 
    case WIDER_RIGHT: 
    case WIDER_BOTH: 
    case NARROWER_LEFT: 
    case NARROWER_RIGHT: 
    case NARROWER_BOTH: 
    case WIDTH: 
w = newWidth = wBox; 
if (font.Family & 1)            /* Variable width or else */ { 
    switch (id) { 
case WIDER_BOTH: 
    w++; 
case WIDER_LEFT: 
case WIDER_RIGHT: 
    w++; 
    break; 
case NARROWER_BOTH: 
    w--; 
case NARROWER_LEFT: 
case NARROWER_RIGHT: 
    w--; 
    break; 
case WIDTH: 
    if (DialogBox(hInst, 
(LPSTR)vszDWidth, hBox, lpWidthProc)) 
w = newWidth; 
    break; 
    } 
 
    if (w < 0 || w >= wBoxLim) { 
MessageBox(hBox, 
(LPSTR)vszEdLimits0To64, 
(LPSTR)szAppName, 
MB_OK | MB_ICONASTERISK); 
break;                  /* Out of range! quit */ 
    } 
    if (w > (LONG) font.MaxWidth) { 
if (IDOK == MessageBox(hBox, 
    (LPSTR)vszMaxWidthIncrease, 
    (LPSTR)szAppName, 
    MB_OKCANCEL | MB_ICONQUESTION)) 
    font.MaxWidth = (WORD)w; 
else 
    break; 
    } 
    BoxBackup();                /* In case we change our minds */ 
    wBox = (WORD)w;             /* Reset width */ 
    fRepaint = TRUE;            /* Signal redraw */ 
    switch (id) { 
    case WIDER_LEFT: 
DupCol(0, kBoxLim - 1); 
for (y = 0; y < kBoxLim; y++) 
    matBox[0][y] = FALSE;       /* Clear left column */ 
break; 
    case WIDER_BOTH:            /* Shift character one right */ 
DupCol(0, kBoxLim - 1); 
for (y = 0; y < kBoxLim; y++) 
    matBox[wBox -1][y] = FALSE; /* Clear right column */ 
for (y = 0; y < kBoxLim; y++) 
    matBox[0][y] = FALSE;       /* Clear left column */ 
break; 
    case NARROWER_LEFT: 
    case NARROWER_BOTH:/* Shift character one left */ 
if (wBox) {/* .. unless width is already 0 */ 
    for (j = 0; j <= kBox - 1; j++) 
for (i = 0; i <= wBox - 1; i++) 
    matBox[i][j] = matBox[i + 1][j]; 
    break; 
} 
    } 
} 
else { 
    MessageBox(hBox, 
    (LPSTR)vszCannotChangeWidth, 
    (LPSTR)szAppName, 
    MB_OK | MB_ICONASTERISK); 
} 
break; 
 
    case ROW_ADD: 
    case ROW_DEL: 
    case COL_ADD: 
    case COL_DEL: 
/* set cursor to "+" shaped cursor */ 
SetCapture (hBox); /* so that cursor doesn't get restored 
      before we are done */ 
hOldCursor = SetCursor (LoadCursor (NULL, IDC_CROSS)); 
fCaptured = TRUE; 
cursor = id; 
break; 
 
    case BOX_CLEAR: 
    case BOX_FILL: 
    case BOX_INV: 
    case BOX_HATCH: 
    case BOX_LEFTRIGHT: 
    case BOX_TOPBOTTOM: 
    case BOX_COPY: 
    case BOX_PASTE: 
/* Get one o' da funky cursors */ 
SetCapture(hBox); 
hOldCursor = SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(id))); 
fStartRubberBand = TRUE; 
CharRectDimensions((LPRECT)&FontRect); 
cursor = id; 
break; 
 
    case BOX_REFRESH:           /* Go get old version of character */ 
BoxBackup();            /* In case we change our minds */ 
CharToBox(iChar); 
hMenu = GetMenu(hBox); 
EnableMenuItem(hMenu, BOX_UNDO, MF_ENABLED);    /* Can Unrefresh! */ 
break; 
    case BOX_UNDO: 
BoxRestore(); 
hMenu = GetMenu(hBox); 
EnableMenuItem(hMenu, BOX_REFRESH, MF_ENABLED); 
fRepaint = TRUE; 
break; 
} 
if (fRepaint) { 
fEdited = fChanged = TRUE; 
InvalidateRect(hBox, (LPRECT)NULL, TRUE); 
} 
} 
 
 
VOID 
CharRectDimensions( 
LPRECT Rect 
) 
/* returns the dimensions of the edit box */ 
{ 
Rect->top    =  ptBox.y; 
Rect->bottom =  ptBox.y + (kBox) * (scale); 
Rect->left   =  ptBox.x; 
Rect->right  =  ptBox.x + (wBox) * (scale); 
} 
 
 
/****************************************************************************** 
 * BOOL  APIENTRY WidthProc(hDial, message, wParam, lParam) 
 * 
 * purpose: dialog function for Width menu function 
 * 
 * params:  same as for all dialog fns. 
 * 
 * side effects: changes Box width variable 
 * 
 *****************************************************************************/ 
BOOL  APIENTRY  
WidthProc( 
HWND   hDial, 
WORD   message, 
WPARAM wParam, 
LPARAM lParam 
) 
{ 
INT i; 
BOOL fOk; 
 
UNREFERENCED_PARAMETER(lParam); 
 
switch (message) { 
default: 
return FALSE; 
case WM_INITDIALOG: 
SetDlgItemInt(hDial, BOX_WIDTH, newWidth, FALSE); 
break; 
 
case WM_COMMAND: 
switch (LOWORD(wParam)) { 
case IDOK: 
fChanged = TRUE; 
i = GetDlgItemInt(hDial, BOX_WIDTH, (LPBOOL)&fOk, FALSE); 
if (fOk && i < wBoxLim) 
newWidth = i; 
else 
ErrorBox(hDial, vszWidthOutOfBounds); 
 
case IDCANCEL: 
EndDialog(hDial, LOWORD(wParam) != IDCANCEL); 
break; 
 
default: 
break; 
} 
} 
return TRUE; 
} 
 
 
/****************************************************************************** 
 * BOOL CheckSave() 
 * 
 * purpose: checks if font is dirty and prompts user to save font. If yes, 
 *          edit box is saved and file save function is called. 
 * 
 * params:  none 
 * 
 * returns: TRUE : font has been changed 
 *          FALSE: font untouched 
 * 
 * side effects: file dirty flag is reset. 
 * 
 *****************************************************************************/ 
BOOL  
CheckSave( 
VOID 
) 
{ 
CHAR * szError;                 /* String for error messages */ 
CHAR szMessage[MAX_STR_LEN+MAX_FNAME_LEN]; 
 
/* Check if anything changed */ 
if (fLoaded && fChanged && (!fReadOnly)) { 
lstrcpy((LPSTR)szNewFile, (LPSTR)szFontFileFull); 
DlgMergeStrings(szSCC, szNewFile, szMessage); 
switch (MessageBox(hFont, 
    (LPSTR)szMessage, 
    (LPSTR)szAppName, 
    MB_YESNOCANCEL | MB_ICONQUESTION)) { 
case IDYES: 
BoxToChar(iChar);            /* Just in case */ 
szError = FontSave (szNewFile, &ofstrFile); 
FontRename(szError);            /* Rename or Print Error */ 
case IDNO: 
return TRUE; 
case IDCANCEL: 
return FALSE; 
} 
} 
return TRUE; 
} 
 
 
/****************************************************************************** 
 * MouseInBox(hBox, message, ptMouse) 
 * 
 * purpose: do edit operation depending on currently active menu command 
 * 
 * params: HWND hBox       : handle to main window 
 *         WORD message    : Message retrieved by main window's window fn. 
 *         POINT ptMouse   : current mouse coordinates 
 * returns: none 
 * 
 * side effects: alters matBox (global 2-d array with ready pixel info. on 
 *               currently displayed box). Also assigns values to ptA and ptB 
 *****************************************************************************/ 
VOID 
MouseInBox( 
HWND hBox, 
WORD message, 
POINT ptMouse 
) 
{ 
POINT pt; 
BOOL fRepaint = FALSE; 
short nct = 0 ; 
 
pt = SnapPointToGrid(ptMouse); 
 
if (pt.x >= 0L && pt.y >= 0L && 
    ((DWORD)pt.x) < wBox && ((DWORD)pt.y) < kBox) { 
fEdited = fChanged = TRUE; 
ptC.x = pt.x; 
ptC.y = pt.y;/* Current square */ 
if (message == WM_LBUTTONDOWN) 
BoxBackup();/* Set up for UNDO */ 
switch (cursor) { 
case BOX_COPY: 
case BOX_PASTE: 
case BOX_CLEAR: 
case BOX_FILL: 
case BOX_INV: 
case BOX_HATCH: 
case BOX_LEFTRIGHT: 
case BOX_TOPBOTTOM: 
ptA.x = pt.x; 
ptA.y = pt.y;/* save anchor point */ 
/* save color under marker */ 
colorA = matBox[pt.x][pt.y]; 
fAll = FALSE; 
 
fRepaint = TRUE; 
break; 
default: 
AddDel(pt.x, pt.y, cursor); 
fRepaint = TRUE; 
cursor = FALSE; 
break; 
case FALSE: 
switch (message) { 
case WM_LBUTTONDOWN:/*invert */ 
nct =1 ; 
colorA = (matBox[pt.x][pt.y] ^= TRUE); 
break; 
 
case WM_LBUTTONUP: 
break; 
 
case WM_MOUSEMOVE: 
matBox[pt.x][pt.y] = colorA;    /* paint */ 
break; 
} 
/* 
if( nct != 0 ) 
{ 
*/ 
fRepaint = TRUE; 
fAll = FALSE;               /* Limited redraw */ 
/* 
} 
*/ 
break; 
} 
if (fRepaint) { 
BoxPaint(); 
return; 
} 
} 
cursor = FALSE; 
} 
 
 
/****************************************************************************** 
 * ReadRect(ptMouse) 
 * 
 * purpose:      defines the rectangular region in edit box to be filled by 
 *               fill menu command  by fixing top left (ptA) and bottom right 
 *               (ptB) coordinates of rect. 
 * 
 * params: 
 * 
 * assumes:that rectRubber is normalized (eg, left < right, botton > top) 
 * 
 * returns:    none 
 * 
 * side effects: alters matBox (global 2-d array with ready pixel info. on 
 *               currently displayed box). Also assigns values to ptA and ptB 
 *****************************************************************************/ 
VOID 
ReadRect( 
) 
{ 
 
ptA.x = (rectRubber.left-(ptBox.x+1))   / scale; 
ptA.y = (rectRubber.top-(ptBox.y+1))    / scale; 
ptB.x = (rectRubber.right-(ptBox.x-2))  / scale - 1; 
ptB.y = (rectRubber.bottom-(ptBox.y-2)) / scale - 1; 
 
if (((DWORD)ptB.x) > wBox - 1) 
    ptB.x = wBox - 1; 
if (((DWORD)ptB.y) > kBox - 1) 
    ptB.y = kBox - 1; 
 
if (ptB.x >= 0 && ptB.y >= 0) { 
    ClearFill((DWORD)ptB.x, (DWORD)ptB.y, cursor);         
    BoxPaint(); 
} 
cursor = FALSE; 
} 
 
 
/****************************************************************************** 
 * ClearFill(col, row, mode) 
 * 
 * purpose:  fill the specified rectangular region in edit box with fill type 
 *           indicated by mode.Top left corner of rect is global(ptA) 
 * 
 * params:   DWORD row : row (of bottom right corner of rect(ptB.x)) 
 *           DWORD col : column (of bottom right corner of rect(ptB.y)) 
 *           WORD mode: action to be performed 
 * 
 * returns:  none 
 * 
 * side effects: alters matBox (global 2-d array with ready pixel info. on 
 *               currently displayed box) 
 *****************************************************************************/ 
VOID 
ClearFill( 
DWORD col,  
DWORD row,  
WORD mode 
) 
{ 
DWORD i, x, y; 
CHAR z; 
 
if (col < (DWORD)ptA.x) /* if points are reversed */ { 
i = col; 
col = ptA.x; 
ptA.x = i; 
}          /* flip them */ 
if (row < (DWORD) ptA.y) { 
i = row; 
row = ptA.y; 
ptA.y = i; 
}          /* flip them */ 
 
if (mode == BOX_LEFTRIGHT) { 
for (x = ptA.x; x <= (DWORD)((ptA.x + col) / 2); x++) 
for (y = ptA.y; y <= row; y++) { 
z = matBox[x][y]; 
matBox[x][y] = matBox[ptA.x + col - x][y]; 
matBox[ptA.x + col - x][y] = z; 
} 
return; 
} 
 
if (mode == BOX_TOPBOTTOM) { 
for (y = ptA.y; y <= ((DWORD)(ptA.y + row) / 2); y++) 
for (x = ptA.x; x <= col; x++) { 
z = matBox[x][y]; 
matBox[x][y] = matBox[x][ptA.y + row - y]; 
matBox[x][ptA.y + row - y] = z; 
} 
return; 
} 
 
if (mode == BOX_COPY) 
BoxToClipboard(ptA, col - ptA.x + 1, row - ptA.y + 1); 
 
if (mode == BOX_PASTE) 
ClipboardToBox(ptA, col - ptA.x + 1, row - ptA.y + 1, FALSE); 
 
for (x = ptA.x; x <= col; x++) 
for (y = ptA.y; y <= row; y++) { 
switch (mode) { 
case BOX_CLEAR: 
case BOX_FILL: 
matBox[x][y] = (CHAR)(mode == BOX_FILL); 
break; 
case BOX_INV: 
matBox[x][y] ^= (CHAR)TRUE; 
break; 
case BOX_HATCH: 
matBox[x][y] = (CHAR)((x+y)%2 ? TRUE : FALSE); 
break; 
} 
} 
} 
 
 
/****************************************************************************** 
 * AddDel(col, row, mode) 
 * 
 * purpose:  Add/Delete row/col as per mode 
 * 
 * params:   DWORD row : row 
 *           DWORD col : column 
 *           WORD mode: action to be performed 
 * 
 * returns:  none 
 * 
 * side effects: alters matBox (global 2-d array with ready pixel info. on 
 *               currently displayed box) 
 *****************************************************************************/ 
VOID 
AddDel( 
DWORD col,  
DWORD row,  
WORD mode 
) 
{ 
switch (mode) { 
case ROW_ADD: 
DupRow(wBox, row); 
break; 
 
case ROW_DEL: 
ZapRow(wBox, row); 
break; 
 
case COL_ADD: 
DupCol(col, kBox); 
break; 
 
case COL_DEL: 
ZapCol(col, kBox); 
break; 
} 
/* restore arrow cursor */ 
SetCursor (hOldCursor); 
ReleaseCapture(); 
fCaptured = FALSE; 
fJustZapped = TRUE; 
} 
 
 
/****************************************************************************** 
 * ZapCol(col, row) 
 * 
 * purpose: delete given column in edit box. Shift cols to right given col 
 *          right. Rightmost column gets duplicated. 
 * 
 * params : DWORD col : column 
 *          DWORD row : row 
 * returns: none 
 * 
 * side effects: alters matBox (global 2-d array with ready pixel info. on 
 *               currently displayed box) 
 *****************************************************************************/ 
VOID 
ZapCol( 
DWORD col,  
DWORD row 
) 
{ 
DWORD x, y; 
for (y = 0; y <= row; y++) 
for (x = col; x < wBox - 1; x++) 
matBox[x][y] = matBox[x + 1][y]; 
for (y = 0; y <= row; y++) 
matBox[x][y] = matBox[x - 1][y]; 
} 
 
 
/****************************************************************************** 
 * ZapRow(col, row) 
 * 
 * purpose: delete given row in edit box. Shift rows below given row up. Lowest 
 *          row gets duplicated 
 * 
 * params:  DWORD col : column 
 *          DWORD row : row 
 * returns: none 
 * 
 * side effects: alters matBox (global 2-d array with ready pixel info. on 
 *               currently displayed box) 
 *****************************************************************************/ 
VOID 
ZapRow( 
DWORD col,  
DWORD row 
) 
{ 
DWORD x, y; 
for (x = 0; x <= col; x++) 
for (y = row; y < kBox - 1; y++) 
matBox[x][y] = matBox[x][y + 1]; 
for (x = 0; x <= col; x++) 
matBox[x][y] = matBox[x][y - 1]; 
} 
 
 
/****************************************************************************** 
 * DupCol(col, row) 
 * 
 * purpose: duplicate given column in edit box. Shift cols to right of given 
 *          col right 
 * 
 * params:  DWORD col : column 
 *          DWORD row : row 
 * returns: none 
 * 
 * side effects: alters matBox (global 2-d array with ready pixel info. on 
*               currently displayed box) 
 *****************************************************************************/ 
VOID 
DupCol( 
DWORD col,  
DWORD row 
) 
{ 
DWORD x, y; 
for (x = wBox - 1; x > col; x--) 
for (y = 0; y <= row; y++) 
matBox[x][y] = matBox[x - 1][y]; 
} 
 
 
/****************************************************************************** 
 * DupRow(col, row) 
 * 
 * purpose: duplicate given row in edit box. Shift rows below given row down. 
 * 
 * params:  DWORD col : column 
 *          DWORD row : row 
 * returns: none 
 * 
 * side effects: alters matBox (global 2-d array with ready pixel info. on 
 *               currently displayed box) 
 *****************************************************************************/ 
VOID 
DupRow( 
DWORD col,  
DWORD row 
) 
{ 
DWORD x, y; 
for (x = 0; x <= col; x++) 
for (y = kBox - 1; y > row; y--) 
matBox[x][y] = matBox[x][y - 1]; 
} 
 
 
/****************************************************************************** 
 * ClearBox(col, row, bb) 
 * 
 * purpose: reset all pixels in edit box (make box white) 
 * 
 * params : none 
 * 
 * returns: none 
 * 
 * side effects: alters matBox (global 2-d array with ready pixel info. on 
 *               currently displayed box) 
 * 
 *****************************************************************************/ 
VOID 
ClearBox( 
VOID 
)                  /* Clear edit box */ 
{ 
DWORD x, y; 
for (x = 0; x < wBoxLim; x++) 
for (y = 0; y < kBoxLim; y++) 
matBox[x][y] = FALSE; 
} 
 
 
/****************************************************************************** 
 * BoxBackup() 
 * 
 * purpose:   makes a backup of pix. info. of currently displayed edit box 
 * 
 * params:    none 
 * 
 * returns:   none 
 * 
 * side effects: alters matBackup (local 2-d array with backup pixel info. 
 *               on edit box ) 
 *****************************************************************************/ 
VOID 
BoxBackup( 
VOID 
) 
{ 
DWORD x, y; 
HMENU hMenu; 
 
hMenu = GetMenu(hBox); 
EnableMenuItem(hMenu, BOX_UNDO, MF_ENABLED); 
EnableMenuItem(hMenu, BOX_REFRESH, MF_ENABLED); 
for (x = 0; x < wBoxLim; x++) 
for (y = 0; y < kBoxLim; y++) 
matBackup[x][y] = matBox[x][y]; 
wBoxBackup = wBox; 
} 
 
 
/****************************************************************************** 
 * BoxRestore() 
 * 
 * purpose : Current edit box and backup box exchange places 
 * 
 * params  : none 
 * 
 * returns : none 
 * 
 * side effects: alters matBox (global 2-d array with ready pixel info. on 
 *               currently displayed box 
 * 
 *****************************************************************************/ 
VOID 
BoxRestore( 
VOID 
)            /* Box and Backup exchange places */ 
{ 
DWORD x, y, temp; 
CHAR z; 
 
for (x = 0; x < wBoxLim; x++) 
for (y = 0; y < kBoxLim; y++) { 
z = matBackup[x][y]; 
matBackup[x][y] = matBox[x][y]; 
matBox[x][y] = z; 
} 
temp = wBox; 
wBox = wBoxBackup; 
wBoxBackup = temp; 
} 
 
 
/****************************************************************************** 
 * POINT SnapPointToGrid (Pt) 
 * 
 * purpose : Intended only for the Fill menu command where rubberbanding rect. 
 *           needs to be aligned on the grid lines. Snap the current mouse 
 *           coordinates to nearest grid intersection. 
 * 
 * params  : POINT Pt : current point mouse is over 
 * 
 * returns : POINT    : number of nearest square 
 * 
 * side effects:      : current mouse coordinate(global variable) altered to 
 *                      return value 
 * 
 *****************************************************************************/ 
POINT  
SnapPointToGrid( 
POINTPt 
) 
{ 
 
Pt.x = (Pt.x - ptBox.x) / scale; 
if (Pt.y > (scale * (font.Ascent - 1))) 
Pt.y = Pt.y - 2;/* Allow for break in box */ 
Pt.y = (Pt.y - ptBox.y) / scale; 
return (Pt); 
} 
 
 
/****************************************************************************** 
 * VOID PASCAL EndRubberBandingRect() 
 * 
 * purpose: Stops rubberbanding rect for Fill menu command and cleans up 
 * 
 * params : HANDLE hDst : handle to dest. DC 
 * 
 * side effects: none 
 * 
 *****************************************************************************/ 
VOID PASCAL  
EndRubberBandingRect( 
HDC hDst  /* handle to dest. DC */ 
) 
{ 
fRubberBanding = FALSE;      /* reset "in-progress" flag */ 
 
ReleaseDC(hBox, hDst); 
ReleaseCapture(); 
SetCursor(hOldCursor); 
} 
 
 
/****************************************************************************** 
 * HDC PASCAL InitialiseRubberBandingRect(hBox) 
 * 
 * purpose: Sets up rubberbanding rect for Fill menu command. 
 * 
 * params : HANDLE hDst : handle to box DC 
 * 
 * returns :handle to destination display context 
 * 
 * side effects: alters few global flags for rubberbanding 
 * 
 *****************************************************************************/ 
HDC PASCAL  
InitialiseRubberBandingRect( 
HWND hBox  /* handle to  DC  of box */ 
) 
{ 
HDC hDst; 
 
fRubberBanding = TRUE;       /* set "in-progress" flag */ 
fStartRubberBand = FALSE;    /* reset "start-proceedings" flag */ 
SetCapture(hBox);            /* send all msgs to current window */ 
 
hDst = GetDC (hBox); 
 
/* select pen and fill mode for rectangle*/ 
hWhitePen  = SelectObject(hDst, GetStockObject (WHITE_PEN)); 
hNullBrush = SelectObject(hDst, GetStockObject (NULL_BRUSH)); 
SetROP2(hDst, R2_XORPEN); 
 
return(hDst); 
} 
 
 
/****************************************************************************** 
 * VOID PASCAL DrawRubberBand() 
 * 
 * purpose: Draw rubberbanding rect for Fill menu command. 
 * 
 * params : HANDLE hDst : handle to dest. DC 
 * 
 * side effects: alters few global flags for rubberbanding 
 * 
 *****************************************************************************/ 
VOID PASCAL  
DrawRubberBand( 
HDC   hDst,                        /*  handle to dest. DC */ 
LPRECTlpRect, 
DWORDrop 
) 
{ 
#ifdef DBG 
charbuf[256]; 
        SIZE        Size; 
        static LONG cxPrev; 
        INT         nLeftRect; 
#endif 
 
SetROP2(hDst, rop); 
Rectangle(hDst, lpRect->left,  lpRect->top, 
lpRect->right, lpRect->bottom); 
 
#ifdef DBG 
sprintf(buf, "left=%d, top=%d, right=%d, bottom=%d",  
lpRect->left,  lpRect->top, lpRect->right, lpRect->bottom); 
    GetTextExtentPoint32(hDst, buf, lstrlen(buf), &Size); 
    nLeftRect = ptBox.x+scale*wBox+16 + Size.cx; 
    if(nLeftRect < cxPrev) { 
        RECT rc; 
        rc.left   = nLeftRect; 
        rc.top    = 14+2*kBox+font.ExtLeading+3*cSysHeight; 
        rc.right  = cxPrev; 
        rc.bottom = 14+2*kBox+font.ExtLeading+3*cSysHeight + Size.cy; 
    FillRect(hDst, &rc, hbrBackGround); 
    } 
    cxPrev = nLeftRect; 
TextOut(hDst, ptBox.x+scale*wBox+16, 
      14+2*kBox+font.ExtLeading+3*cSysHeight, 
      buf, strlen(buf)); 
#endif 
} 
 
 
/****************************************************************************** 
 * long  APIENTRY FontEditWndProc(hBox, message, wParam, lParam) 
 * 
 * purpose: Master controller for Fontedit's all-encompassing main window 
 * 
 * params : same as for all window functions 
 * 
 * side effects: countless 
 * 
 *****************************************************************************/ 
LONG  APIENTRY  
FontEditWndProc( 
HWND   hBox, 
WORD   message, 
WPARAM wParam, 
LPARAM lParam 
) 
{ 
PAINTSTRUCTps; 
HMENUhMenu; 
WORDmf; 
POINTpt; 
RECTBoxRect; 
 
switch (message) { 
case WM_CLOSE: 
if (!CheckSave())    /* See if any files need saving */ 
break; 
/* Window's being destroyed. */ 
if (fLoaded)         /* 4/8/87 Linsh added */ 
DeleteGlobalBitmap(); /* Get rid of memory DC */ 
DestroyWindow(hFont); 
DestroyWindow(hBox); 
break; 
 
case WM_DESTROY: 
PostQuitMessage(0);  /* Cause application to be terminated */ 
break; 
 
case WM_QUERYENDSESSION: 
if (CheckSave())             /* See if any files need saving */ 
return TRUE; 
break; 
 
case WM_ENDSESSION: 
if (fLoaded) 
DeleteGlobalBitmap();      /* Get rid of memory DC */ 
break; 
 
case WM_SIZE: 
/* Window's size is changing.  lParam contains the width 
        ** and height, in the low and high words, respectively. 
        ** wParam contains SIZENORMAL for "normal" size changes, 
        ** SIZEICONIC when the window is being made iconic, and 
        ** SIZEFULLSCREEN when the window is being made full screen. */ 
switch (wParam) { 
case SIZEFULLSCREEN: 
case SIZENORMAL: 
ResizeShow(); 
if (kStuff != GetkStuff())/* Did it change ? */ 
ResizeShow();           /* Yes resize again */ 
break; 
} 
break; 
 
case WM_MOVE: /* Tell popup to move with us. */ 
if (!IsIconic(hBox)) 
ResizeShow(); 
break; 
 
case WM_PAINT: 
/* Time for the window to draw itself. */ 
BeginPaint(hBox, (LPPAINTSTRUCT)&ps); 
FontEditPaint(hBox,  ps.hdc); 
EndPaint(hBox, (LPPAINTSTRUCT)&ps); 
break; 
 
 
case WM_COMMAND: 
/* A menu item has been selected, or a control is notifying 
 * its parent.  wParam is the menu item value (for menus), 
 * or control ID (for controls).  For controls, the low word 
 * of lParam has the window handle of the control, and the hi 
 * word has the notification code.  For menus, lParam contains 
 * 0L. */ 
FontEditCommand(hBox, LOWORD(wParam)); 
break; 
 
/* Data interchange request. */ 
case WM_CUT: 
case WM_COPY: 
case WM_PASTE: 
case WM_CLEAR: 
case WM_UNDO: 
case WM_RENDERFORMAT: 
case WM_RENDERALLFORMATS: 
case WM_DESTROYCLIPBOARD: 
case WM_DRAWCLIPBOARD: 
break; 
case WM_INITMENU: 
hMenu = GetMenu(hBox);  /* Gray menu if no clipboard bitmap */ 
mf = (WORD)(IsClipboardFormatAvailable(CF_BITMAP) ? MF_ENABLED :  
MF_GRAYED); 
EnableMenuItem(hMenu, BOX_PASTE, mf); 
EnableMenuItem(hMenu, FONT_PASTE, mf); 
break; 
 
/* For each of following mouse window messages, wParam contains 
** bits indicating whether or not various virtual keys are down, 
** and lParam is a POINT containing the mouse coordinates.   The 
** keydown bits of wParam are:  MK_LBUTTON (set if Left Button is 
** down); MK_RBUTTON (set if Right Button is down); MK_SHIFT (set 
** if Shift Key is down); MK_ALTERNATE (set if Alt Key is down); 
** and MK_CONTROL (set if Control Key is down). */ 
 
case WM_LBUTTONDOWN: 
((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y); 
 
if (fStartRubberBand) { 
/* a green signal to rubberband a rectangle for the 
 * Fill menu command rectangle now has null dimensions. 
 * Snap the current mouse point to nearest grid 
 * intersection thus defining upper left corner of 
 * rectangle */ 
 
if (PtInRect((LPRECT)&FontRect, pt)) { 
pt = SnapPointToGrid(pt); 
rectRubber.top    =  pt.y   *scale+ptBox.y+1; 
rectRubber.bottom = (pt.y+1)*scale+ptBox.y-2; 
rectRubber.left   =  pt.x   *scale+ptBox.x+1; 
rectRubber.right  = (pt.x+1)*scale+ptBox.x-2; 
 
hDst = InitialiseRubberBandingRect(hBox); 
DrawRubberBand(hDst, &rectRubber, R2_XORPEN); 
} 
else { 
fStartRubberBand = fRubberBanding = FALSE; 
ReleaseCapture(); 
} 
} 
/* do operation depending upon current active command, 
 * but not if we just added/deleted a row/column. */ 
if (!fJustZapped) { 
if (fStartRubberBand) { 
pt.x *= scale; 
pt.y *= scale; 
MouseInBox(hBox, message, pt); 
} 
else { 
((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y); 
MouseInBox(hBox, message, pt); 
} 
} 
 
break; 
 
case WM_LBUTTONUP:               /* Get other corner of rectangle */ 
fJustZapped = FALSE; 
if (fRubberBanding) { 
/* if rubberbanding for the Fill menu command, 
 * terminate proceedings and clean up */ 
DrawRubberBand(hDst, &rectRubber, R2_NOT); 
EndRubberBandingRect(hDst); 
if (cursor) { 
ReadRect(); 
} 
} 
if (fCaptured ) { 
/* if cursor is + shaped, restore it to default */ 
ReleaseCapture(); 
SetCursor (hOldCursor); 
} 
break; 
 
case WM_RBUTTONDOWN: 
case WM_RBUTTONUP: 
break; 
 
case WM_MOUSEMOVE:                      /* If mouse is down */ 
 
((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y); 
 
if ((fRubberBanding) && (wParam & MK_LBUTTON)) { 
/* if any of Fill menu commands is active 
** (AND the mouse key depressed) draw a rubberband 
** a rectangle with the mouse movements */ 
 
/* get current square number */ 
pt = SnapPointToGrid(pt); 
 
/* calculate grid for new square */ 
BoxRect.top    =  pt.y   *scale+ptBox.y+1; 
BoxRect.bottom = (pt.y+1)*scale+ptBox.y-2; 
BoxRect.left   =  pt.x   *scale+ptBox.x+1; 
BoxRect.right  = (pt.x+1)*scale+ptBox.x-2; 
 
/* erase old mark */ 
DrawRubberBand(hDst, &rectRubber, R2_NOT); 
 
/* limit rubber band to box */ 
if (BoxRect.right > (LONG) (scale * wBox + ptBox.x)) 
BoxRect.right = scale * wBox + ptBox.x; 
if (BoxRect.bottom > (LONG) (scale * kBox + ptBox.y)) 
BoxRect.bottom = scale * kBox + ptBox.y; 
if (BoxRect.top < 0) 
BoxRect.top = 1; 
if (BoxRect.left < 0) 
BoxRect.left = 1; 
 
if (ptA.x == pt.x) { 
rectRubber.right  = BoxRect.right; 
rectRubber.left   = BoxRect.left; 
} 
if (ptA.y == pt.y) { 
rectRubber.bottom = BoxRect.bottom; 
rectRubber.top    = BoxRect.top; 
} 
 
/* almost an IntersectRect */ 
if (ptA.x >= pt.x) 
rectRubber.left   = BoxRect.left; 
else 
rectRubber.right  = BoxRect.right; 
 
if (ptA.y >= pt.y) 
rectRubber.top    = BoxRect.top; 
else 
rectRubber.bottom = BoxRect.bottom; 
 
/* Draw new mark */ 
DrawRubberBand(hDst, &rectRubber, R2_XORPEN); 
} 
else { 
/* if not "Fill"ing(AND mouse key depressed, 
 * paint with the mouse movements */ 
if ((wParam & MK_LBUTTON) && cursor == FALSE &&  
    fJustZapped == FALSE) 
MouseInBox(hBox, message, pt); 
} 
break; 
 
case WM_LBUTTONDBLCLK: 
case WM_RBUTTONDBLCLK: 
break; 
 
default: 
 
/* Everything else comes here.  This call MUST exist 
        ** in your window proc.  */ 
 
return(DefWindowProc(hBox, message, wParam, lParam)); 
break; 
} 
 
/* A window proc should always return something */ 
return(0L); 
} 
 
 
/***************************** Public  Function ****************************\ 
* 
* BOOL  APIENTRY AboutDlg(hDlg, message, wParam, lParam) 
* HWND     hDlg; 
* WORD message; 
* WPARAM wParam; 
* LPARAM lParam; 
* 
* 
* Effects: none. 
* 
\***************************************************************************/ 
BOOL  APIENTRY  
AboutDlg( 
HWND   hDlg, 
WORD   message, 
WPARAM wParam, 
LPARAM lParam 
) 
{ 
UNREFERENCED_PARAMETER(lParam); 
 
switch (message) { 
case WM_INITDIALOG: 
break; 
 
case WM_COMMAND: 
EndDialog(hDlg, LOWORD(wParam)); 
/* idok or idcancel */ 
break; 
 
default: 
return FALSE; 
break; 
} 
return(TRUE); 
}