home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / showcp.zip / showcp.c < prev    next >
C/C++ Source or Header  |  1999-01-28  |  90KB  |  3,247 lines

  1. /*
  2.  * showcp: Show Codepages
  3.  *
  4.  * Function:
  5.  *     This application display and prints codepages in OS/2 PM.
  6.  *     This is done as a test of the PM codepage and font support.
  7.  *     It also acts as online unicode and codepage documentation.
  8.  *
  9.  * Notes:
  10.  *
  11.  * Todo:
  12.  *     - Font selecton
  13.  *     - Help
  14.  */
  15.  
  16. /*
  17.  *  Include files
  18.  */
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <wcstr.h>
  22. #include <stdlib.h>
  23. #include <ctype.h>
  24. #include <io.h>
  25. #include <direct.h>
  26.  
  27. #define  INCL_PM
  28. #define  INCL_SPL
  29. #define  INCL_SPLDOSPRINT
  30. #define  INCL_DOS
  31. #include <os2.h>
  32. #define INCL_GRE_STRINGS
  33. #include <pmddi.h>
  34.  
  35. #include "showcp.h"
  36.  
  37. /*
  38.  *  Global variables
  39.  */
  40. HWND hwndMainFrame = NULLHANDLE;    /* handle to the main frame window */
  41. HWND hwndMain;                      /* handle to the main client window */
  42. HDC  hdcMain;                       /* handle to the DC of the client */
  43. HAB  hab;                           /* anchor block for the process */
  44. HMQ  hmq;                           /* handle to the process' message queue */
  45. CHAR szAppName[MAXNAMEL];           /* buffer for application name string */
  46. BOOL fHelpEnabled;                  /* flag to determine if help is enabled */
  47. UniChar * FileBuf, * CurFileBuf;
  48. int  FontNum;
  49. int  Linesize   = 30;
  50. int  Textsize   = 20;
  51. int  LineOffset = 7;
  52. int  TabSize    = 34;
  53. int  Equalsize  = 110;
  54. int  Leftmar    = 50;
  55. int  Ward       = 0;
  56. int  InWard     = 0;
  57. int  Info       = 0;
  58. int  InInfo     = 0;
  59.  
  60. int  HoverMax;
  61. int  HoverLen;
  62. int  HoverInfo;
  63.  
  64. char * Font;
  65. char   DbcsStarter[256];
  66. char   DbcsSecond[256];
  67. UconvObject UconvO;
  68. UconvObject Uconv1207, Uconv1386, Uconv949;
  69. int    Codepage;
  70. char   CodeName[64];
  71. int    FontCp;
  72. int    FontSize;
  73. int    TopPos, LeftPos;
  74. int    IsDbcs;
  75. int    Match4, Match5;
  76. char * UniTable;
  77. char   Debugflag;
  78. char   Sizeflag;
  79.  
  80. int    doargs(int argc, char * * argv);
  81. void   setsizes(void);
  82. int    QueryPrintQueue(char * qname, char * drvname);
  83. VOID   Print(int showuni);
  84.  
  85. /*
  86.  * Font name mapping
  87.  */
  88. char * Fonts[] = {
  89.    "Times New Roman",       "Times New Roman Bold",  "Times New Roman Italic", "Times New Roman Bold Italic",
  90.    "Helvetica",             "Helvetica Bold",        "Helvetica Italic",      "Helvetica Bold Italic",
  91.    "Courier",               "Courier Bold",          "Courier Italic",        "Courier Bold Italic",
  92.    "System Proportional",   "System Proportional",   "System Proportional",   "System Proportional",
  93.    "System VIO",            "System VIO",            "System VIO",            "System VIO",
  94.    "Times New Roman MT 30", "DFP-SMTWSong",          "Times New Roman MT 30", "Times New Roman MT 30",
  95.    "Arial",                 "Arial Bold",            "Arial Italic",          "Arial Bold Italic",
  96.    "Symbol",                "Symbol",                "Symbol",                "Symbol",
  97.    "Wingdings",             "Wingdings",             "Wingdings",             "Wingdings",
  98.    "ITC Zapf Dingbats",     "ITC Zapf Dingbats",     "ITC Zapf Dingbats",     "ITC Zapf Dingbats",
  99.    "Tms Rmn",               "Tms Rmn ISO",           "Tms Rmn",               "Tms Rmn",
  100.    "Helv",                  "Helv ISO",              "Helv",                  "Helv",
  101.    "Courier New",           "Courier New Bold",      "Courier New Italic",    "Courier New Bold Italic",
  102.    "Bitstream Cyberbit",    "Bitstream Cyberbit",    "Bitstream Cyberbit",    "Bitstream Cyberbit",
  103.    "Lucida Sans Unicode",   "Lucida Sans Unicode",   "Monotype.com",          "Monotype.com",
  104.    "HeiseiMincho-W3-90-TT", "HeiseiKakuGothic-W5-90-TT", "HeiseiMincho-W3-90-TT", "HeiseiKakuGothic-W5-90-TT",
  105.    "Times New Roman WT J",  "Times New Roman WT J",  "Times New Roman WT J",   "Times New Roman WT J",
  106.    "Monotype Sans Duospace WT J",  "Monotype Sans WT",  "Monotype Sans Duospace WT J",   "Monotype Sans Duospace WT J",
  107.    "", "", "", "",
  108. };
  109.  
  110.  
  111. /*
  112.  *
  113.  * main:  Set up PM
  114.  *
  115.  */
  116. int main(int argc, char * * argv) {
  117.     QMSG    qmsg;          /* message structure */
  118.     ULONG   ctldata;       /* frame control data */
  119.     int     i, rc;
  120.     char  * arg;
  121.     UniChar glyphs[20];
  122.     SWP     deskp, winp;
  123.  
  124.     /*
  125.      * Create the HAB and Message Queues
  126.      */
  127.     hab = WinInitialize(0);
  128.     hmq = WinCreateMsgQueue(hab, 0);
  129.  
  130.     /*
  131.      * Process arguments and do initialization
  132.      */
  133.     doargs(argc, argv);
  134.     if (!Init()) {
  135.         MessageBox(HWND_DESKTOP, IDMSG_INITFAILED,
  136.                   MB_OK | MB_ERROR, TRUE);
  137.         return 1;
  138.     }
  139.  
  140.     /* NOTE:  clean up from here is handled by the DosExitList processing */
  141.  
  142.     /*
  143.      * create the main window
  144.      */
  145.     ctldata = FCF_STANDARD;
  146.     hwndMainFrame = WinCreateStdWindow(HWND_DESKTOP,
  147.                                        WS_VISIBLE,
  148.                                        &ctldata,
  149.                                        (PSZ)szAppName,
  150.                                        (PSZ)NULL,
  151.                                        WS_VISIBLE,
  152.                                        (HMODULE)NULL,
  153.                                        IDR_MAIN,
  154.                                        (PHWND)&hwndMain);
  155.  
  156.     if (!hwndMainFrame) {
  157.         MessageBox(HWND_DESKTOP,
  158.                    IDMSG_MAINWINCREATEFAILED,
  159.                    MB_OK | MB_ERROR,
  160.                    TRUE);
  161.         return 1;
  162.     }
  163.  
  164.     /*
  165.      * Make sure the window is on the screen.  This is important because
  166.      * we do not support scrolling.
  167.      */
  168.     hdcMain = WinOpenWindowDC(hwndMain);
  169.     WinQueryWindowPos(HWND_DESKTOP, &deskp);
  170.     setsizes();
  171.     WinSetWindowPos(hwndMainFrame, NULL, 0, 0, TabSize*18, Linesize*20, SWP_SIZE);
  172.     WinQueryWindowPos(hwndMainFrame, &winp);
  173.     if (winp.y + Linesize*20 > deskp.cy) {
  174.         WinSetWindowPos(hwndMainFrame, NULL, winp.x, deskp.cy - Linesize*20, 0, 0, SWP_MOVE);
  175.     }
  176.  
  177.  
  178.     /*
  179.      * No help yet
  180.      */
  181.     /* InitHelp(); */
  182.  
  183.  
  184.     /*
  185.      * Get/Dispatch Message loop
  186.      */
  187.     while(WinGetMsg(hab, (PQMSG)&qmsg, (HWND)NULL, (ULONG)NULL, (ULONG)NULL))
  188.         WinDispatchMsg(hab, (PQMSG)&qmsg);
  189.  
  190.     /*
  191.      * No help yet
  192.      */
  193.     /* DestroyHelpInstance(); */
  194.  
  195.      return 0;
  196. }
  197.  
  198.  
  199. /*
  200.  *  doargs:  Process arguments
  201.  */
  202. int doargs(int argc, char * * argv) {
  203.     int       argcnt;
  204.     char  *   argp;
  205.     char      swchar;
  206.  
  207.     argcnt = 1;
  208.     Sizeflag = 2;
  209.     FontSize = 14;
  210.     /*
  211.      * Read the arguments and decide what we are doing
  212.      */
  213.     while (argcnt<argc) {
  214.         argp = argv[argcnt];
  215.         /*
  216.          * Check for switches.
  217.          */
  218.         if (*argp == '-' && argp[1]) {
  219.             /* Process switches */
  220.             swchar = (char)tolower(argp[1]);
  221.             argp += 2;
  222.             switch (swchar) {
  223.  
  224.             /*
  225.              * -s -- Small flag
  226.              */
  227.             case 's':
  228.                 Sizeflag = 1;
  229.                 FontSize = 12;
  230.                 break;
  231.  
  232.             /*
  233.              * -l -- Large flag
  234.              */
  235.             case 'l':
  236.                 Sizeflag = 3;
  237.                 FontSize = 14;
  238.                 break;
  239.  
  240.             /*
  241.              * -d -- Debug option.
  242.              */
  243.             case 'd':
  244.                 Debugflag = 1;
  245.                 if (argp[-1]=='D') Debugflag=2;
  246.                 break;
  247.             }
  248.         } else {
  249.             Codepage = atoi(argp);
  250.         }
  251.         argcnt++;
  252.     }
  253.     return 0;
  254. }
  255.  
  256.  
  257. /*
  258.  * setsizes: Set basic sizes
  259.  */
  260. void setsizes(void) {
  261.     HPS    hps;
  262.     HDC    hdc;
  263.     LONG  fontres;
  264.  
  265.     /*
  266.      * If size is not set by user, default it based on screen resolution
  267.      */
  268.     if (Sizeflag==2) {
  269.         hps = WinGetPS(HWND_DESKTOP);
  270.         hdc = GpiQueryDevice(hps);
  271.         DevQueryCaps(hdc, CAPS_HORIZONTAL_FONT_RES, 1, &fontres);
  272.         if (fontres<100) {
  273.             Sizeflag = 1;
  274.             FontSize = 12;
  275.         } else {
  276.             Sizeflag = 3;
  277.             FontSize = 14;
  278.         }
  279.     }
  280.  
  281.     /*
  282.      * Set for small size
  283.      */
  284.     if (Sizeflag<2) {
  285.         Linesize   = 24;
  286.         Textsize   = 16;
  287.         LineOffset = 6;
  288.         TabSize    = 27;
  289.     }
  290.     /*
  291.      * Set for large size
  292.      */
  293.     else {
  294.         Linesize   = 30;
  295.         Textsize   = 20;
  296.         LineOffset = 7;
  297.         TabSize    = 34;
  298.     }
  299. }
  300.  
  301.  
  302. /*
  303.  * MainWndProc: Main window procedure
  304.  *
  305.  */
  306. MRESULT EXPENTRY MainWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) {
  307.     int  i;
  308.     int  dodefault = 0;
  309.     RECTL  rect;
  310.  
  311.     switch(msg) {
  312.     case WM_CREATE:
  313.        return InitMainWindow(hwnd, mp1, mp2);
  314.        break;
  315.  
  316.     case WM_PAINT:
  317.         MainPaint(hwnd);
  318.         break;
  319.  
  320.     case WM_MOUSEMOVE:
  321.         dodefault = 1;
  322.         i = getposition(SHORT1FROMMP(mp1), SHORT2FROMMP(mp1));
  323.         if (i != HoverInfo) {
  324.             rect.xLeft   = 0;
  325.             rect.xRight  = HoverLen;
  326.             rect.yTop    = HoverMax;
  327.             rect.yBottom = HoverMax-Linesize;
  328.             WinInvalidateRect(hwnd, &rect, FALSE);
  329.             HoverInfo = i;
  330.         }
  331.         break;
  332.  
  333.     case WM_BUTTON1DOWN:
  334.         dodefault = 1;
  335.         i = getposition(SHORT1FROMMP(mp1), SHORT2FROMMP(mp1));
  336.         if (i>255) {
  337.             if (InInfo) {
  338.                 InInfo = 0;
  339.                 Info = 0;
  340.                 setupfont(hwnd);
  341.             } else {
  342.                 if (InWard) {
  343.                     Ward = 0;
  344.                     InWard = 0;
  345.                     setupfont(hwnd);
  346.                 }
  347.             }
  348.             break;
  349.         }
  350.         if (InWard == 0 && DbcsStarter[i]==2) {
  351.             Ward = i;
  352.             InWard = 1;
  353.             setupfont(hwnd);
  354.             break;
  355.         }
  356.         if ((InWard == 0 && DbcsStarter[i]==1) ||
  357.             (InWard && DbcsSecond[i]==1) ) {
  358.             Info = i;
  359.             InInfo = 1;
  360.             setupfont(hwnd);
  361.         }
  362.         break;
  363.  
  364.     case WM_COMMAND:
  365.         MainCommand(mp1, mp2, hwnd);
  366.         break;
  367.  
  368.     case WM_INITMENU:
  369.         InitMenu(mp1, mp2);
  370.         break;
  371.  
  372.     case HM_QUERY_KEYS_HELP:
  373.         return (MRESULT)PANEL_HELPKEYS;   /* return id of key help panel */
  374.         break;
  375.  
  376.     default:    /* default must call WinDefWindowProc() */
  377.         dodefault = 1;
  378.         break;
  379.     }
  380.  
  381.     if (dodefault)
  382.          return WinDefWindowProc(hwnd, msg, mp1, mp2);
  383.     return (MRESULT)0;
  384. }
  385.  
  386.  
  387. /*
  388.  * MessageBox: Show a message
  389.  */
  390. ULONG MessageBox(HWND hwndOwner, ULONG idMsg, ULONG fsStyle, BOOL fBeep) {
  391.     CHAR szText[MESSAGELEN];
  392.  
  393.     if (!WinLoadMessage(hab, (HMODULE)NULL, idMsg, MESSAGELEN, (PSZ)szText)) {
  394.         WinAlarm(HWND_DESKTOP, WA_ERROR);
  395.         return MBID_ERROR;
  396.     }
  397.  
  398.     if (fBeep)
  399.         WinAlarm(HWND_DESKTOP, WA_ERROR);
  400.  
  401.     return(WinMessageBox(HWND_DESKTOP, hwndOwner, szText, (PSZ)NULL, MSGBOXID,
  402.                          fsStyle));
  403. }
  404.  
  405.  
  406. /*
  407.  * setupfont: Set up font
  408.  */
  409. void setupfont(HWND hwnd) {
  410.     int     rc;
  411.     ULONG   codepage;
  412.     char    fontname[128];
  413.  
  414.     /*
  415.      * Change the Win codepage.  This should not really be necessary, but
  416.      * it has the virtue of actually working.
  417.      */
  418.     if (Codepage == 1200) {
  419.         if (Ward>=0x34 && Ward<0xf8) {
  420.             if (Ward>=0xac && Ward<0xd8)
  421.                 WinSetCp(hmq, 949);
  422.             else
  423.                 WinSetCp(hmq, 1386);
  424.         } else {
  425.             WinSetCp(hmq, 1207);
  426.         }
  427.     }
  428.     sprintf(fontname, "%d.%s", FontSize, Font);
  429.  
  430.     /*
  431.      * This should be changed someday since this has significant problems
  432.      * when there are multiple fonts by the same name.
  433.      */
  434.     WinSetPresParam(hwndMain, PP_FONTNAMESIZE,
  435.                     (ULONG)strlen(fontname) + 1,
  436.                     (PVOID)fontname);
  437.     WinInvalidateRect( hwnd, NULL, FALSE );
  438.     UpdateTitleText(hwndMainFrame);
  439. }
  440.  
  441.  
  442. /*
  443.  * setupcp:  Set up codepage
  444.  */
  445. int setupcp(int codepage) {
  446.     UniChar cpname[64];
  447.     ULONG   cplist[128], * cpl;
  448.     int     rc;
  449.     int     count;
  450.     uconv_attribute_t attr;
  451.     UconvObject uo;
  452.  
  453.     /*
  454.      * Make sure PM knows about this codepage
  455.      */
  456.     count = WinQueryCpList(hab, 128, cplist);
  457.     cpl = cplist;
  458.     while (count) {
  459.         if (*cpl == codepage)
  460.             break;
  461.         count--;
  462.         cpl++;
  463.     }
  464.     if (count==0 && codepage != 1200) {
  465.         MessageBox(HWND_DESKTOP, IDMSG_NOCP, MB_OK | MB_ERROR, TRUE);
  466.         return 1;
  467.     }
  468.  
  469.     /*
  470.      * Make sure we have a ULS conversion object
  471.      */
  472.     UniMapCpToUcsCp(codepage, cpname, 16);
  473.     UniStrcat(cpname, L"@path=no,map=display");
  474.     rc = UniCreateUconvObject(cpname, &uo);
  475.     if (rc) {
  476.         MessageBox(HWND_DESKTOP, IDMSG_NOCP, MB_OK | MB_ERROR, TRUE);
  477.         return 1;
  478.     }
  479.  
  480.     /*
  481.      * Make sure we have the other necessary converters
  482.      */
  483.     if (codepage == 1200 && !Uconv1207) {
  484.         UniCreateUconvObject(L"IBM-1207",         &Uconv1207);
  485.         UniCreateUconvObject(L"IBM-1386@path=no", &Uconv1386);
  486.         UniCreateUconvObject(L"IBM-949@path=no",  &Uconv949);
  487.         if (!Uconv1207 || !Uconv1386 || !Uconv949) {
  488.             MessageBox(HWND_DESKTOP, IDMSG_NOCP, MB_OK | MB_ERROR, TRUE);
  489.             return 1;
  490.         }
  491.     }
  492.  
  493.     /*
  494.      * This is supposed to always work since we checked if the codepage
  495.      * was supported above.  This fails for some DBCS versions.  In any
  496.      * case, the return code is unreliable, so we ignore it.  (The return
  497.      * code is bad due to an uninitialized variable in winres.c which will
  498.      * be fixed for Aurora).
  499.      */
  500.     rc = WinSetCp(hmq, codepage==1200?1207:codepage);
  501.  
  502.     /*
  503.      * Switch to the new codepage
  504.      */
  505.     Codepage = codepage;
  506.     CodeName[0] = 0;
  507.     WinLoadString(hab, (HMODULE)0, Codepage+IDM_CODEPAGE, 64, CodeName);
  508.     Ward = 0;
  509.     InWard = 0;
  510.     if (UconvO)
  511.         UniFreeUconvObject(UconvO);
  512.     UconvO = uo;
  513.  
  514.     /*
  515.      * Circumvent a bug in QueryUconvObject.  This is fixed now, but this
  516.      * makes it work on older systems.
  517.      */
  518.     UniQueryUconvObject(UconvO, &attr, sizeof(attr), DbcsStarter, DbcsSecond, NULL);
  519.     if (Codepage == 1200) {
  520.         memset(DbcsStarter,        2,    256);
  521.         memset(DbcsStarter+0xD8,   0xff, 8);
  522.         memset(DbcsSecond,         1,    256);
  523.     }
  524.     if (Codepage == 1207) {
  525.         memset(DbcsStarter,        1,    128);
  526.         memset(DbcsStarter+0x80,   2,    128);
  527.         memset(DbcsStarter+0xe8,   0xff, 8);
  528.         memset(DbcsStarter+0xF0,   3,    4);
  529.         memset(DbcsSecond,         0,    128);
  530.         memset(DbcsSecond+0x80,    1,    128);
  531.     }
  532.     if (Codepage == 1208) {
  533.         memset(DbcsStarter,        1,    128);
  534.         memset(DbcsStarter+0x80,   0xff, 64);
  535.         memset(DbcsStarter+0xc0,   2,    32);
  536.         memset(DbcsStarter+0xe0,   3,    32);
  537.         memset(DbcsSecond,         0,    256);
  538.         memset(DbcsSecond+0x80,    1,    64);
  539.     }
  540.  
  541.     /*
  542.      * Select if this is DBCS
  543.      */
  544.     if (attr.mb_max_len > 1)
  545.         IsDbcs = 1;
  546.     else
  547.         IsDbcs = 0;
  548.  
  549.     return 0;
  550. }
  551.  
  552.  
  553. /*
  554.  * createfonts:  Create logical fonts
  555.  */
  556. void createfonts(HPS hps) {
  557.     FATTRS  fat;
  558.     HDC     hdc;
  559.     int     rc;
  560.     char    names[256];
  561.     LONG    types[16], ids[16];
  562.     FONTMETRICS * fm, * buf;
  563.     LONG    count, i, fontres;
  564.  
  565.     /*
  566.      * If we have already found the font, do not look again
  567.      */
  568.     if (!Match4) {
  569.         buf = malloc(64000);
  570.         count = 64000/sizeof(FONTMETRICS);
  571.         hps = WinGetPS(HWND_DESKTOP);
  572.         hdc = GpiQueryDevice(hps);
  573.         DevQueryCaps(hdc, CAPS_HORIZONTAL_FONT_RES, 1, &fontres);
  574.         rc  = GpiQueryFonts (hps, QF_PUBLIC, "Helv", &count,
  575.                            sizeof(*fm), (FONTMETRICS *)buf);
  576.  
  577.         fm = buf;
  578.         for (i=0; i<count; i++) {
  579.             if (fontres==fm->sXDeviceRes) {
  580.                 if (fm->sNominalPointSize == ((Sizeflag<2) ? 80 : 100))
  581.                     Match4 = fm->lMatch;
  582.                 if (fm->sNominalPointSize == ((Sizeflag<2) ? 100 : 120))
  583.                     Match5 = fm->lMatch;
  584.             }
  585.             fm++;
  586.         }
  587.         free(buf);
  588.     }
  589.  
  590.     /*
  591.      * Create the fonts in this PS
  592.      */
  593.     memset(&fat, 0, sizeof(FATTRS));
  594.     fat.usRecordLength = sizeof(FATTRS);
  595.     strcpy(fat.szFacename, "Helv");
  596.     fat.usCodePage = 850;
  597.     fat.lMatch = Match4;
  598.     rc = GpiCreateLogFont(hps, (PSTR8)"helv10", 4, &fat);
  599.     fat.lMatch = Match5;
  600.     rc = GpiCreateLogFont(hps, (PSTR8)"helv12", 5, &fat);
  601.     rc = GpiQuerySetIds(hps, 16, types, (PSTR8)names, ids);
  602. }
  603.  
  604.  
  605. /*
  606.  * MainCommand: Process dialog commands
  607.  */
  608. VOID MainCommand(MPARAM mp1, MPARAM mp2, HWND hwnd) {
  609.     UniChar * pos;
  610.     int       i;
  611.     int       rc;
  612.  
  613.     i = SHORT1FROMMP(mp1);
  614.  
  615.     /*
  616.      * Select a codepage
  617.      */
  618.     if (i>IDM_CODEPAGE && i<IDM_CODEPAGE+4095) {
  619.         setupcp(i-10000);
  620.         setupfont(hwnd);
  621.         return;
  622.     }
  623.  
  624.     /*
  625.      * Select a font
  626.      */
  627.     if (i>IDM_FONT && i<IDM_FONT+100) {
  628.         FontNum = i-IDM_FONT-4;
  629.         Font = Fonts[FontNum];
  630.         setupfont(hwnd);
  631.         return;
  632.     }
  633.  
  634.     /*
  635.      * Set size
  636.      */
  637.     if (i>IDM_SIZE && i<IDM_SIZE+100) {
  638.         FontSize = i-IDM_SIZE;
  639.         setupfont(hwnd);
  640.         return;
  641.     }
  642.  
  643.  
  644.     switch(i) {
  645.     /*
  646.      * Set attibutes
  647.      */
  648.     case IDM_NORMAL:
  649.         Font = Fonts[FontNum];
  650.         setupfont(hwnd);
  651.         break;
  652.  
  653.     case IDM_BOLD:
  654.         Font = Fonts[FontNum + 1];
  655.         setupfont(hwnd);
  656.         break;
  657.  
  658.     case IDM_ITALIC:
  659.         Font = Fonts[FontNum + 2];
  660.         setupfont(hwnd);
  661.         break;
  662.  
  663.     case IDM_BOLDITALIC:
  664.         Font = Fonts[FontNum + 3];
  665.         setupfont(hwnd);
  666.         break;
  667.  
  668.     /*
  669.      * Terminate
  670.      */
  671.     case IDM_EXIT:
  672.         exit(1);
  673.         break;
  674.  
  675.     /*
  676.      * Go back a level (escape key)
  677.      */
  678.     case IDM_ESCAPE:
  679.         if (InInfo) {
  680.             InInfo = 0;
  681.             Info = 0;
  682.             setupfont(hwnd);
  683.             break;
  684.         }
  685.         if (InWard) {
  686.             Ward = 0;
  687.             InWard = 0;
  688.             setupfont(hwnd);
  689.         }
  690.         break;
  691.  
  692.     /*
  693.      * Previous page
  694.      */
  695.     case IDM_PAGEUP:
  696.         if (InInfo) {
  697.             Info--;
  698.             if (Info<0)
  699.                 Info = 255;
  700.             WinInvalidateRect( hwnd, NULL, FALSE );
  701.             break;
  702.         }
  703.         if (InWard) {
  704.             i = Ward - 1;
  705.             while (i >= 0) {
  706.                 if (DbcsStarter[i] == 2) {
  707.                     Ward = i;
  708.                     setupfont(hwnd);
  709.                     break;
  710.                 }
  711.                 i--;
  712.             }
  713.             if (i<0) {
  714.                 Ward = 0;
  715.                 InWard = 0;
  716.             }
  717.             setupfont(hwnd);
  718.         }
  719.         break;
  720.  
  721.     /*
  722.      * Next page
  723.      */
  724.     case IDM_PAGEDOWN:
  725.         if (InInfo) {
  726.             Info++;
  727.             if (Info>255)
  728.                 Info = 0;
  729.             WinInvalidateRect( hwnd, NULL, FALSE );
  730.             break;
  731.         }
  732.         if (InWard) {
  733.             i = Ward + 1;
  734.             while (i < 256) {
  735.                 if (DbcsStarter[i] == 2) {
  736.                     Ward = i;
  737.                     setupfont(hwnd);
  738.                     break;
  739.                 }
  740.                 i++;
  741.             }
  742.             if (i>255) {
  743.                 InWard = 0;
  744.                 Ward = 0;
  745.             }
  746.             setupfont(hwnd);
  747.         }
  748.         break;
  749.  
  750.     /*
  751.      * Print with annotation
  752.      */
  753.     case IDM_PRINT:
  754.         Print(1);
  755.         break;
  756.  
  757.     /*
  758.      * Print without annotation
  759.      */
  760.     case IDM_PRINTI:
  761.         Print(2);
  762.         break;
  763.  
  764.     /*
  765.      * Print without annotation
  766.      */
  767.     case IDM_PRINTNU:
  768.         Print(0);
  769.         break;
  770.  
  771.     case IDM_HELPINDEX:
  772.         HelpIndex();
  773.         break;
  774.  
  775.     case IDM_HELPGENERAL:
  776.         HelpGeneral();
  777.         break;
  778.  
  779.     case IDM_HELPUSINGHELP:
  780.         HelpUsingHelp();
  781.         break;
  782.  
  783.     case IDM_HELPKEYS:
  784.         HelpKeys();
  785.         break;
  786.  
  787.     case IDM_HELPTUTORIAL:
  788.         HelpTutorial();
  789.         break;
  790.  
  791.     case IDM_HELPPRODUCTINFO:
  792.         HelpProductInfo();
  793.         break;
  794.  
  795.     default:
  796.         break;
  797.     }
  798. }
  799.  
  800.  
  801. /*
  802.  * getposition: Get mouse position
  803.  */
  804. int  getposition(int x, int y) {
  805.     int  xx, yy;
  806.     int  topoff;
  807.  
  808.     if (InInfo) {
  809.         return 256;
  810.     }
  811.     topoff = TopPos - LineOffset;
  812.     if (x<LeftPos || x>(LeftPos+16*TabSize) ||
  813.         y>(topoff)  || y<(topoff-16*Linesize) ) {
  814.         return 256;
  815.     }
  816.     xx = (x-LeftPos)/TabSize;
  817.     yy = -(y-topoff)/Linesize;
  818.     return (yy<<4) + xx;
  819. }
  820.  
  821.  
  822. /*
  823.  * painthover: Paint the hover information
  824.  */
  825. void painthover(HPS hps) {
  826.     char    info[256];
  827.     int     rc;
  828.     POINTL  point;
  829.     char    charbuf[4];
  830.     UniChar unis[4];
  831.     char *  cp, * token[16], temp[128];
  832.  
  833.     if (HoverInfo<256) {
  834.         if (!InWard && DbcsStarter[HoverInfo] != 1) {
  835.             return;
  836.         }
  837.  
  838.         if (Codepage == 1200) {
  839.             unis[0] = (Ward<<8) | HoverInfo;
  840.             unis[1] = 0;
  841.         } else {
  842.             if (InWard == 0) {
  843.                 charbuf[0] = HoverInfo;
  844.                 charbuf[1] = 0;
  845.             } else {
  846.                 charbuf[0] = Ward;
  847.                 charbuf[1] = HoverInfo;
  848.                 charbuf[2] = 0;
  849.             }
  850.             UniStrToUcs(UconvO, unis, charbuf, 4);
  851.         }
  852.         if (InWard) {
  853.             sprintf(info, "%02x%02x  %3d/%-3d", Ward, HoverInfo, Ward, HoverInfo);
  854.         } else {
  855.             sprintf(info, "0x%02x  %3d", HoverInfo, HoverInfo);
  856.         }
  857.         if (unis[0] != 0xfffd) {
  858.             sprintf(info+strlen(info), "  U%04x", unis[0]);
  859.             getglyph(unis[0]);
  860.             if (!*GlyphAdobe && !*GlyphIBM && unis[0]) {
  861.                 cp = getuniinfo(unis[0]);
  862.                 if (*cp) {
  863.                     tokenuni(cp, temp, token);
  864.                     if (token[1]) {
  865.                         cp = info+strlen(info);
  866.                         strcpy(cp, " - ");
  867.                         strcat(cp, token[1]);
  868.                         strlwr(cp);
  869.                     }
  870.                 }
  871.             } else {
  872.                 if (*GlyphAdobe) {
  873.                     strcat(info, " - ");
  874.                     strcat(info, GlyphAdobe);
  875.                 }
  876.                 if (*GlyphIBM) {
  877.                     strcat(info, " - ");
  878.                     strcat(info, GlyphIBM);
  879.                 }
  880.             }
  881.         }
  882.  
  883.         GpiSetCharSet(hps, 4);
  884.         point.x = LeftPos;
  885.         point.y = HoverMax-Textsize;
  886.         GpiMove(hps, &point);
  887.         rc = GpiCharString(hps, strlen(info), info);
  888.     }
  889. }
  890.  
  891.  
  892. /*
  893.  * dogrid: Put out the grid system
  894.  */
  895. void dogrid(HPS hps) {
  896.     int    rc, i;
  897.     ULONG  len, ulen;
  898.     char   charbuf[4];
  899.     POINTL point;
  900.  
  901.     point.x = LeftPos -8;
  902.     for (i=0; i<=16; i++) {
  903.         point.y = TopPos - LineOffset;
  904.         GpiMove(hps, &point);
  905.         point.y -= Linesize * 16;
  906.         GpiLine(hps, &point);
  907.         point.x += TabSize;
  908.     }
  909.  
  910.     point.y = TopPos - LineOffset;
  911.     for (i=0; i<=16; i++) {
  912.         point.x = 42;
  913.         GpiMove(hps, &point);
  914.         point.x += TabSize * 16;
  915.         GpiLine(hps, &point);
  916.         point.y -= Linesize;
  917.     }
  918.  
  919.     point.x = LeftPos;
  920.     point.y = TopPos;
  921.     charbuf[0] = '-';
  922.     charbuf[2] = 0;
  923.     len = 2;
  924.     GpiSetCharSet(hps, 5);
  925.     for (i=0; i<16; i++) {
  926.         GpiMove(hps, &point);
  927.         charbuf[1] = hexstr[i];
  928.         rc = GpiCharString(hps, len, charbuf);
  929.         point.x += TabSize;
  930.     }
  931.  
  932.     point.x = LeftPos - 35;
  933.     point.y = TopPos - Linesize;
  934.     charbuf[1] = '-';
  935.     charbuf[2] = 0;
  936.     len = 2;
  937.     GpiSetCharSet(hps, 5);
  938.     for (i=0; i<16; i++) {
  939.         GpiMove(hps, &point);
  940.         charbuf[0] = hexstr[i];
  941.         rc = GpiCharString(hps, len, charbuf);
  942.         point.y -= Linesize;
  943.     }
  944. }
  945.  
  946.  
  947. /*
  948.  *  MainPaint: Paint the client window
  949.  */
  950. VOID MainPaint(HWND hwnd) {
  951.     RECTL rclUpdate;
  952.     RECTL rectl;
  953.     POINTL point;
  954.     SIZEF  sizef;
  955.     HPS hps;
  956.     int    rc, i;
  957.     ULONG  len, ulen;
  958.     char   charbuf[4], strbuf[100], temp[256];
  959.     char * token[16];
  960.     long   saveid, saveclr;
  961.     UniChar unis[4];
  962.     char * cp, * tp;
  963.  
  964.     hps = WinBeginPaint(hwnd, NULLHANDLE, &rclUpdate);
  965.  
  966.     /*
  967.      * fill update rectangle with window color
  968.      */
  969.     WinQueryWindowRect( hwnd, &rectl );
  970.     WinFillRect(hps, &rectl, SYSCLR_WINDOW);
  971.     if (!Font) {
  972.         Font = "Times New Roman MT 30";
  973.         FontNum = 20;
  974.         if (!Codepage) {
  975.             Codepage = WinQueryCp(hmq);
  976.         }
  977.         if (setupcp(Codepage)) {
  978.             Codepage = WinQueryCp(hmq);
  979.             setupcp(Codepage);
  980.         }
  981.         setupfont(hwnd);
  982.     }
  983.     TopPos  = rectl.yTop - Textsize;
  984.     HoverMax = TopPos - (Linesize*16+LineOffset);
  985.     LeftPos = 50;
  986.     HoverLen = LeftPos + TabSize * 16;
  987.     saveid = GpiQueryCharSet(hps);
  988.     createfonts(hps);
  989.  
  990.     GpiSetCp(hps, 850);
  991.  
  992.     /*
  993.      * Show the info page
  994.      */
  995.     if (InInfo) {
  996.         GpiSetCharSet(hps, 5);
  997.  
  998.         point.x = Leftmar;
  999.         point.y = TopPos - 220;
  1000.         GpiMove(hps, &point);
  1001.         GpiCharString(hps, 8, "Codepage");
  1002.         point.x = Leftmar+Equalsize;
  1003.         GpiMove(hps, &point);
  1004.  
  1005.         sprintf(strbuf, "= %d - %s", Codepage, CodeName);
  1006.         rc = GpiCharString(hps, strlen(strbuf), strbuf);
  1007.  
  1008.         point.x = Leftmar;
  1009.         point.y -= Textsize;
  1010.         GpiMove(hps, &point);
  1011.         GpiCharString(hps, 4, "Font");
  1012.         point.x = Leftmar+Equalsize;
  1013.         GpiMove(hps, &point);
  1014.         sprintf(strbuf, "= %s", Font);
  1015.         rc = GpiCharString(hps, strlen(strbuf), strbuf);
  1016.  
  1017.         point.x = Leftmar;
  1018.         point.y -= Textsize;
  1019.         GpiMove(hps, &point);
  1020.         GpiCharString(hps, 9, "Codepoint");
  1021.         point.x = Leftmar+Equalsize;
  1022.         GpiMove(hps, &point);
  1023.         if (InWard) {
  1024.             sprintf(strbuf, "= %02X%02X", Ward, Info);
  1025.         } else {
  1026.             sprintf(strbuf, "= %02X (%d)", Info, Info);
  1027.         }
  1028.         rc = GpiCharString(hps, strlen(strbuf), strbuf);
  1029.  
  1030.  
  1031.         point.x = Leftmar;
  1032.         point.y -= Textsize;
  1033.         GpiMove(hps, &point);
  1034.         GpiMove(hps, &point);
  1035.         GpiCharString(hps, 7, "UniCode");
  1036.         point.x = Leftmar+Equalsize;
  1037.         GpiMove(hps, &point);
  1038.  
  1039.         if (Codepage == 1200) {
  1040.             unis[0] = (Ward<<8) | Info;
  1041.             unis[1] = 0;
  1042.             memset(charbuf, 0, 4);
  1043.             if (Ward>=0x34 && Ward<0xf8) {
  1044.                 if (Ward>=0xac && Ward<0xd8)
  1045.                     UniStrFromUcs(Uconv949, charbuf, unis, 4);
  1046.                 else
  1047.                     UniStrFromUcs(Uconv1386, charbuf, unis, 4);
  1048.             } else {
  1049.                 UniStrFromUcs(Uconv1207, charbuf, unis, 4);
  1050.             }
  1051.             len = strlen(charbuf);
  1052.         } else {
  1053.             if (InWard == 0) {
  1054.                 charbuf[0] = Info;
  1055.                 charbuf[1] = 0;
  1056.                 len = 1;
  1057.             } else {
  1058.                 charbuf[0] = Ward;
  1059.                 charbuf[1] = Info;
  1060.                 charbuf[2] = 0;
  1061.                 len = 2;
  1062.             }
  1063.             UniStrToUcs(UconvO, unis, charbuf, 4);
  1064.         }
  1065.         sprintf(strbuf, "= %04X", unis[0]);
  1066.         rc = GpiCharString(hps, strlen(strbuf), strbuf);
  1067.  
  1068.         /*
  1069.          * Put out Adobe glyph name
  1070.          */
  1071.         getglyph(unis[0]);
  1072.         if (*GlyphAdobe) {
  1073.             point.x = Leftmar;
  1074.             point.y -= Textsize;
  1075.             GpiMove(hps, &point);
  1076.             GpiCharString(hps, 10, "Glyph name");
  1077.             point.x = Leftmar+Equalsize;
  1078.             GpiMove(hps, &point);
  1079.             sprintf(strbuf, "= %s", GlyphAdobe);
  1080.             rc = GpiCharString(hps, strlen(strbuf), strbuf);
  1081.         }
  1082.  
  1083.         /*
  1084.          * Put out IBM Glpyh name
  1085.          */
  1086.         if (*GlyphIBM) {
  1087.             point.x = Leftmar;
  1088.             point.y -= Textsize;
  1089.             GpiMove(hps, &point);
  1090.             GpiCharString(hps, 9, "IBM glyph");
  1091.             point.x = Leftmar+Equalsize;
  1092.             GpiMove(hps, &point);
  1093.             sprintf(strbuf, "= %s", GlyphIBM);
  1094.             rc = GpiCharString(hps, strlen(strbuf), strbuf);
  1095.         }
  1096.  
  1097.         /*
  1098.          * Put out the data from the unicode tables
  1099.          */
  1100.         cp = getuniinfo(unis[0]);
  1101.         if (*cp) {
  1102.             tokenuni(cp, temp, token);
  1103.  
  1104.             /*
  1105.              * Description
  1106.              */
  1107.             if (*token[1]) {
  1108.                 point.x = Leftmar;
  1109.                 point.y -= Textsize;
  1110.                 GpiMove(hps, &point);
  1111.                 GpiCharString(hps, 11, "Description");
  1112.                 point.x = Leftmar+Equalsize;
  1113.                 GpiMove(hps, &point);
  1114.                 if (!strcmp(token[1], "<control>")) {
  1115.                     sprintf(strbuf, "= %s %s", token[1], token[10]);
  1116.                 } else {
  1117.                     sprintf(strbuf, "= %s", token[1]);
  1118.                 }
  1119.                 strlwr(strbuf);
  1120.                 rc = GpiCharString(hps, strlen(strbuf), strbuf);
  1121.             }
  1122.  
  1123.             /*
  1124.              * Type
  1125.              */
  1126.             if (*token[2]) {
  1127.                 point.x = Leftmar;
  1128.                 point.y -= Textsize;
  1129.                 GpiMove(hps, &point);
  1130.                 GpiCharString(hps, 4, "Type");
  1131.                 point.x = Leftmar+Equalsize;
  1132.                 GpiMove(hps, &point);
  1133.                 cp = getdesc(token[2], UniTypes);
  1134.                 sprintf(strbuf, "= %s", cp);
  1135.                 rc = GpiCharString(hps, strlen(strbuf), strbuf);
  1136.             }
  1137.  
  1138.             /*
  1139.              * Direction
  1140.              */
  1141.             if (*token[4]) {
  1142.                 point.x = Leftmar;
  1143.                 point.y -= Textsize;
  1144.                 GpiMove(hps, &point);
  1145.                 GpiCharString(hps, 9, "Direction");
  1146.                 point.x = Leftmar+Equalsize;
  1147.                 GpiMove(hps, &point);
  1148.                 if (*token[9] == 'Y') {
  1149.                     cp = getdesc("MN", BidiTypes);
  1150.                 } else {
  1151.                     cp = getdesc(token[4], BidiTypes);
  1152.                 }
  1153.                 sprintf(strbuf, "= %s", cp);
  1154.                 rc = GpiCharString(hps, strlen(strbuf), strbuf);
  1155.             }
  1156.  
  1157.             /*
  1158.              * Compose
  1159.              */
  1160.             if (*token[5]) {
  1161.                 point.x = Leftmar;
  1162.                 point.y -= Textsize;
  1163.                 GpiMove(hps, &point);
  1164.                 GpiCharString(hps, 7, "Compose");
  1165.                 point.x = Leftmar+Equalsize;
  1166.                 GpiMove(hps, &point);
  1167.                 sprintf(strbuf, "= %s", token[5]);
  1168.                 rc = GpiCharString(hps, strlen(strbuf), strbuf);
  1169.             }
  1170.         }
  1171.  
  1172.         /*
  1173.          * Set the codepage
  1174.          */
  1175.         if (Codepage != 1200) {
  1176.             GpiSetCp(hps, Codepage);
  1177.         } else {
  1178.             if (Ward>=0x34 && Ward<0xf8)
  1179.                 if (Ward>=0xac && Ward<0xd8)
  1180.                     GpiSetCp(hps, 949);
  1181.                 else
  1182.                     GpiSetCp(hps, 1386);
  1183.             else
  1184.                 GpiSetCp(hps, 1207);
  1185.         }
  1186.  
  1187.         /*
  1188.          * Set the font back to the original
  1189.          */
  1190.         GpiSetCharSet(hps, saveid);
  1191.  
  1192.         /*
  1193.          * Show a big version of the character
  1194.          */
  1195.         point.x = 100;
  1196.         point.y = TopPos-150;
  1197.         GpiMove(hps, &point);
  1198.         sizef.cx = MAKEFIXED(150, 0);
  1199.         sizef.cy = MAKEFIXED(150, 0);
  1200.         GpiSetCharBox(hps, &sizef);
  1201.         GpiCharString(hps, len, charbuf);
  1202.     }
  1203.  
  1204.     /*
  1205.      * Show a grid page
  1206.      */
  1207.     else {
  1208.         if (rclUpdate.yTop <= HoverMax) {
  1209.             painthover(hps);
  1210.             WinEndPaint(hps);
  1211.             return;
  1212.         }
  1213.         /*
  1214.          * Output the grid
  1215.          */
  1216.         dogrid(hps);
  1217.         painthover(hps);
  1218.  
  1219.         /*
  1220.          * Put out DBCS
  1221.          */
  1222.         if (IsDbcs) {
  1223.             saveclr = GpiQueryColor(hps);
  1224.             GpiSetColor(hps, CLR_RED);
  1225.             point.y = TopPos - Linesize;
  1226.             GpiSetCharSet(hps, 4);
  1227.             point.x = LeftPos;
  1228.             for (i=0; i<256; i++) {
  1229.                 if (InWard == 0 && DbcsStarter[i] == 2) {
  1230.                     rc = GpiSetCurrentPosition(hps, &point);
  1231.                     charbuf[0] = hexstr[i>>4];
  1232.                     charbuf[1] = hexstr[i&0xf];
  1233.                     rc = GpiCharString(hps, 2, charbuf);
  1234.                 }
  1235.                 point.x += TabSize;
  1236.                 if ((i&0x0f) == 0x0f) {
  1237.                     point.x = LeftPos;
  1238.                     point.y -= Linesize;
  1239.                 }
  1240.             }
  1241.             GpiSetColor(hps, saveclr);
  1242.             GpiSetCharSet(hps, saveid);
  1243.         }
  1244.  
  1245.         /*
  1246.          * Set the codepage and font for the character display
  1247.          */
  1248.         if (Codepage != 1200) {
  1249.             GpiSetCp(hps, Codepage);
  1250.         } else {
  1251.             if (Ward>=0x34 && Ward<0xf8)
  1252.                 if (Ward>=0xac && Ward<0xd8)
  1253.                     GpiSetCp(hps, 949);
  1254.                 else
  1255.                     GpiSetCp(hps, 1386);
  1256.             else
  1257.                 GpiSetCp(hps, 1207);
  1258.         }
  1259.         GpiSetCharSet(hps, saveid);
  1260.  
  1261.         /*
  1262.          * Show all characters
  1263.          */
  1264.         point.y = TopPos - Linesize;
  1265.         point.x = LeftPos;
  1266.         for (i=0; i<256; i++) {
  1267.             /*
  1268.              * Single byte or zero ward
  1269.              */
  1270.             if (InWard == 0) {
  1271.                 charbuf[0] = i;
  1272.                 charbuf[1] = 0;
  1273.                 len = 1;
  1274.                 UniStrToUcs(UconvO, unis, charbuf, 4);
  1275.                 if (unis[0] == 0xfffd)
  1276.                     len = 0;
  1277.             } else {
  1278.                 /*
  1279.                  * Unicode
  1280.                  */
  1281.                 if (Codepage == 1200) {
  1282.                     unis[0] = (Ward<<8) | i;
  1283.                     unis[1] = 0;
  1284.                     if (Ward>=0x34 && Ward<0xf8) {
  1285.                         if (Ward>=0xac && Ward<0xd8)
  1286.                             UniStrFromUcs(Uconv949, charbuf, unis, 4);
  1287.                         else
  1288.                             UniStrFromUcs(Uconv1386, charbuf, unis, 4);
  1289.                     } else {
  1290.                         UniStrFromUcs(Uconv1207, charbuf, unis, 4);
  1291.                     }
  1292.                     len = strlen(charbuf);
  1293.                 }
  1294.                 /*
  1295.                  * DBCS
  1296.                  */
  1297.                 else {
  1298.                     charbuf[0] = Ward;
  1299.                     charbuf[1] = i;
  1300.                     charbuf[2] = 0;
  1301.                     len = 2;
  1302.                     UniStrToUcs(UconvO, unis, charbuf, 4);
  1303.                     if (unis[0] == 0xfffd)
  1304.                         len = 0;
  1305.                 }
  1306.             }
  1307.  
  1308.             /*
  1309.              * Display the character
  1310.              */
  1311.             if ((InWard == 0 && DbcsStarter[i] == 1) ||
  1312.                 (InWard != 0 && DbcsSecond[i] != 0)) {
  1313.                 if (len) {
  1314.                     /*
  1315.                      * Ignore controls
  1316.                      */
  1317.                     if (!UniQueryChar(unis[0], CT_CNTRL)) {
  1318.                         rc = GpiSetCurrentPosition(hps, &point);
  1319.                         rc = GpiCharString(hps, len, charbuf);
  1320.                     }
  1321.                 }
  1322.             }
  1323.  
  1324.             /*
  1325.              * Move to the next character
  1326.              */
  1327.             point.x += TabSize;
  1328.             if ((i&0x0f) == 0x0f) {
  1329.                 point.x = LeftPos;
  1330.                 point.y -= Linesize;
  1331.             }
  1332.         }
  1333.     }
  1334.  
  1335.     WinEndPaint(hps);
  1336. }
  1337.  
  1338.  
  1339. /*
  1340.  * createprintfonts: Create fonts for the printer
  1341.  */
  1342. void createprintfonts(HPS hps) {
  1343.     FATTRS  fat;
  1344.     ULONG   rc;
  1345.     ULONG   cp;
  1346.     FONTMETRICS * fm, * buf;
  1347.     LONG    count, i, fontres;
  1348.     LONG    match;
  1349.  
  1350.     /*
  1351.      * Force the use of non-device outline fonts
  1352.      */
  1353.     buf = malloc(64000);
  1354.     count = 64000/sizeof(FONTMETRICS);
  1355.     rc  = GpiQueryFonts (hps, QF_PUBLIC | QF_NO_DEVICE, Font, &count,
  1356.                        sizeof(*fm), (FONTMETRICS *)buf);
  1357.  
  1358.     fm = buf;
  1359.     for (i=0; i<count; i++) {
  1360.         if (fm->fsDefn & FM_DEFN_OUTLINE) {
  1361.             match = fm->lMatch;
  1362.             break;
  1363.         }
  1364.         fm++;
  1365.     }
  1366.     free(buf);
  1367.  
  1368.     memset(&fat, 0, sizeof(FATTRS));
  1369.     fat.usRecordLength = sizeof(FATTRS);
  1370.     fat.fsFontUse = FATTR_FONTUSE_OUTLINE;
  1371.     fat.lMatch = match;
  1372.  
  1373.     cp = Codepage;
  1374.     if (Codepage == 1200) {
  1375.         if (Ward>=0x34 && Ward<0xf8) {
  1376.             if (Ward>=0xac && Ward<0xd8)
  1377.                 cp = 949;
  1378.             else
  1379.                 cp = 1386;
  1380.         } else {
  1381.             cp = 1207;
  1382.         }
  1383.     }
  1384.  
  1385.     GpiSetCp(hps, cp);
  1386.     strcpy(fat.szFacename, Font);
  1387.     rc = GpiCreateLogFont(hps, (PSTR8)"basefnt", 2, &fat);
  1388.  
  1389.     WinSetCp(hmq, 850);
  1390.     strcpy(fat.szFacename, "Helvetica");
  1391.     fat.lMatch = 0;
  1392.     rc = GpiCreateLogFont(hps, (PSTR8)"helv10", 1, &fat);
  1393. }
  1394.  
  1395. /*
  1396.  * Print: Print the page
  1397.  *
  1398.  * Function:
  1399.  *     Draw a grid containing 256 codepoints to the default printer
  1400.  *
  1401.  *
  1402.  */
  1403. VOID Print(int showuni) {
  1404.     POINTL    point;
  1405.     SIZEF     sizef;
  1406.     HPS       hps;
  1407.     int       rc, i;
  1408.     ULONG     len, ulen;
  1409.     char      charbuf[20], strbuf[256], temp[256];
  1410.     char    * token[16];
  1411.     long      saveid, saveclr;
  1412.     UniChar   unis[4];
  1413.     char    * cp, * tp;
  1414.     DEVOPENSTRUC  dos;
  1415.     SIZEL     sizel;
  1416.     HDC       prhdc;
  1417.     HPS       prhps;
  1418.     SIZEF     cbox, svbox;
  1419.     int       topPos, leftPos, lineSize, tabSize, lineOffset;
  1420.     UniChar   uni[256];
  1421.     UNICTYPE  * utype;
  1422.  
  1423.     /*
  1424.      * Set up the DC for printing.  Use the default printer
  1425.      */
  1426.     rc = QueryPrintQueue(strbuf, temp);
  1427.     if (rc) {
  1428.         MessageBox(HWND_DESKTOP, IDMSG_NOPRINTER,
  1429.                  MB_OK | MB_ERROR, TRUE);
  1430.         return;
  1431.     }
  1432.     if (strchr(temp, '.'))
  1433.         *(strchr(temp, '.')) = 0;
  1434.  
  1435.     memset(&dos, 0, sizeof(dos));
  1436.     dos.pszLogAddress = strbuf;
  1437.     dos.pszDriverName = temp;
  1438.     dos.pszDataType = "PM_Q_RAW";
  1439.     prhdc = DevOpenDC( hab, OD_QUEUED, "*", 4L, (PVOID)&dos, (HDC)NULL );
  1440.  
  1441.     /*
  1442.      * Create a PS over the printer device.  Use whatever paper size exists.
  1443.      * Create the units as 1/1440 inch.
  1444.      */
  1445.     sizel.cx = 0;
  1446.     sizel.cy = 0;
  1447.     prhps = GpiCreatePS( hab, prhdc, &sizel, PU_TWIPS | GPIA_ASSOC );
  1448.  
  1449.     /*
  1450.      * Start the job
  1451.      */
  1452.     if (InWard) {
  1453.         sprintf(temp, "Codepage %d [%02x]", Codepage, Ward);
  1454.     } else {
  1455.         sprintf(temp, "Codepage %d", Codepage);
  1456.     }
  1457.     DevEscape( prhdc, DEVESC_STARTDOC, strlen(temp), (PBYTE)temp,
  1458.                     (PLONG)NULL, (PBYTE)NULL );
  1459.  
  1460.     /*
  1461.      * Specify the size and positions.  All units in 1/1440 inch
  1462.      */
  1463.     topPos  = 12300;
  1464.     leftPos = 1200;
  1465.     lineSize = 580;
  1466.     tabSize  = 580;
  1467.     lineOffset = 200;
  1468.  
  1469.     /*
  1470.      * Create the fonts in this PS.  We create two fonts, the character font,
  1471.      * and a Helvetica font for other information.
  1472.      */
  1473.     createprintfonts(prhps);
  1474.  
  1475.     /*
  1476.      * Put out the title and font lines
  1477.      */
  1478.     GpiSetCp(prhps, 850);
  1479.     GpiSetCharSet(prhps, 1);
  1480.     cbox.cx = MAKEFIXED(400, 0);
  1481.     cbox.cy = MAKEFIXED(400, 0);
  1482.     GpiSetCharBox(prhps, &cbox);
  1483.  
  1484.     if (InWard) {
  1485.         sprintf(temp, "Codepage %d [%02x] - %s", Codepage, Ward, CodeName);
  1486.     } else {
  1487.         sprintf(temp, "Codepage %d - %s", Codepage, CodeName);
  1488.     }
  1489.     point.y = topPos + lineSize*2;
  1490.     point.x = leftPos - 380;
  1491.     GpiMove(prhps, &point);
  1492.     len = strlen(temp);
  1493.     rc = GpiCharString(prhps, len, temp);
  1494.  
  1495.     cbox.cx = MAKEFIXED(240, 0);
  1496.     cbox.cy = MAKEFIXED(240, 0);
  1497.     GpiSetCharBox(prhps, &cbox);
  1498.     point.y -= 400;
  1499.     GpiMove(prhps, &point);
  1500.     len = strlen(Font);
  1501.     rc = GpiCharString(prhps, len, Font);
  1502.  
  1503.     /*
  1504.      * Output the vertical lines of the grid
  1505.      */
  1506.     point.x = leftPos - 100;
  1507.     for (i=0; i<=16; i++) {
  1508.         point.y = topPos - lineOffset;
  1509.         GpiMove(prhps, &point);
  1510.         point.y -= lineSize * 16;
  1511.         GpiLine(prhps, &point);
  1512.         point.x += tabSize;
  1513.     }
  1514.  
  1515.     /*
  1516.      * Output the horizontal lines of the grid
  1517.      */
  1518.     point.y = topPos - lineOffset;
  1519.     for (i=0; i<=16; i++) {
  1520.         point.x = leftPos - 100;
  1521.         GpiMove(prhps, &point);
  1522.         point.x += tabSize * 16;
  1523.         GpiLine(prhps, &point);
  1524.         point.y -= lineSize;
  1525.     }
  1526.  
  1527.     /*
  1528.      * Output the top legend
  1529.      */
  1530.     point.x = leftPos + 100;
  1531.     point.y = topPos - 90;
  1532.     charbuf[0] = '-';
  1533.     charbuf[2] = 0;
  1534.     len = 2;
  1535.     for (i=0; i<16; i++) {
  1536.         GpiMove(prhps, &point);
  1537.         charbuf[1] = hexstr[i];
  1538.         rc = GpiCharString(prhps, len, charbuf);
  1539.         point.x += tabSize;
  1540.     }
  1541.  
  1542.     /*
  1543.      * Output the left legend
  1544.      */
  1545.     point.x = leftPos - 400;
  1546.     point.y = topPos - lineSize;
  1547.     charbuf[1] = '-';
  1548.     charbuf[2] = 0;
  1549.     len = 2;
  1550.     GpiSetCharSet(prhps, 1);
  1551.     for (i=0; i<16; i++) {
  1552.         GpiMove(prhps, &point);
  1553.         charbuf[0] = hexstr[i];
  1554.         rc = GpiCharString(prhps, len, charbuf);
  1555.         point.y -= lineSize;
  1556.     }
  1557.  
  1558.     /*
  1559.      * Put out DBCS sections
  1560.      */
  1561.     if (IsDbcs) {
  1562.         saveclr = GpiQueryColor(prhps);
  1563.         GpiSetColor(prhps, CLR_RED);
  1564.         point.y = topPos - lineSize;
  1565.         cbox.cx = MAKEFIXED(180, 0);
  1566.         cbox.cy = MAKEFIXED(180, 0);
  1567.         GpiSetCharBox(prhps, &cbox);
  1568.         point.x = leftPos;
  1569.         for (i=0; i<256; i++) {
  1570.             if (InWard == 0 && DbcsStarter[i] == 2) {
  1571.                 rc = GpiSetCurrentPosition(prhps, &point);
  1572.                 charbuf[0] = hexstr[i>>4];
  1573.                 charbuf[1] = hexstr[i&0xf];
  1574.                 rc = GpiCharString(prhps, 2, charbuf);
  1575.             }
  1576.             point.x += tabSize;
  1577.             if ((i&0x0f) == 0x0f) {
  1578.                 point.x = leftPos;
  1579.                 point.y -= lineSize;
  1580.             }
  1581.         }
  1582.         GpiSetColor(prhps, saveclr);
  1583.     }
  1584.  
  1585.     /*
  1586.      * Set the codepage for the characters
  1587.      */
  1588.     if (Codepage != 1200) {
  1589.         GpiSetCp(prhps, Codepage);
  1590.     } else {
  1591.         if (Ward>=0x34 && Ward<0xf8)
  1592.             if (Ward>=0xac && Ward<0xd8)
  1593.                 GpiSetCp(prhps, 949);
  1594.             else
  1595.                 GpiSetCp(prhps, 1386);
  1596.         else
  1597.             GpiSetCp(prhps, 1207);
  1598.     }
  1599.  
  1600.     /*
  1601.      * Set the font for the characters
  1602.      */
  1603.     GpiSetCharSet(prhps, 2);
  1604.     cbox.cx = MAKEFIXED(340, 0);
  1605.     cbox.cy = MAKEFIXED(340, 0);
  1606.     GpiSetCharBox(prhps, &cbox);
  1607.  
  1608.     /*
  1609.      * Draw the characters
  1610.      */
  1611.     memset(uni, 0, 512);
  1612.     point.y = topPos - lineSize;
  1613.     point.x = leftPos;
  1614.     for (i=0; i<256; i++) {
  1615.  
  1616.         /*
  1617.          * Single byte or leading byte
  1618.          */
  1619.         if (InWard == 0) {
  1620.             charbuf[0] = i;
  1621.             charbuf[1] = 0;
  1622.             len = 1;
  1623.             UniStrToUcs(UconvO, unis, charbuf, 4);
  1624.             if (unis[0] == 0xfffd)
  1625.                 len = 0;
  1626.         } else {
  1627.             /*
  1628.              * Unicode display
  1629.              */
  1630.             if (Codepage == 1200) {
  1631.                 unis[0] = (Ward<<8) | i;
  1632.                 unis[1] = 0;
  1633.                 if (Ward>=0x34 && Ward<0xf8) {
  1634.                     if (Ward>=0xac && Ward<0xd8)
  1635.                         UniStrFromUcs(Uconv949, charbuf, unis, 4);
  1636.                     else
  1637.                         UniStrFromUcs(Uconv1386, charbuf, unis, 4);
  1638.                 } else {
  1639.                     UniStrFromUcs(Uconv1207, charbuf, unis, 4);
  1640.                 }
  1641.                 len = strlen(charbuf);
  1642.  
  1643.                 /*
  1644.                  * Do not show characters which are not defined in unicode
  1645.                  */
  1646.                 utype = UniQueryCharType(unis[0]);
  1647.                 if (utype->charset == CHS_NONCHAR)
  1648.                     len = 0;
  1649.             }
  1650.             /*
  1651.              * DBCS display
  1652.              */
  1653.             else {
  1654.                 charbuf[0] = Ward;
  1655.                 charbuf[1] = i;
  1656.                 charbuf[2] = 0;
  1657.                 len = 2;
  1658.                 UniStrToUcs(UconvO, unis, charbuf, 4);
  1659.                 if (unis[0] == 0xfffd)
  1660.                     len = 0;
  1661.             }
  1662.         }
  1663.  
  1664.         /*
  1665.          * Draw the character itself
  1666.          */
  1667.         if ((InWard == 0 && DbcsStarter[i] == 1) ||
  1668.             (InWard != 0 && DbcsSecond[i] != 0)) {
  1669.             if (len) {
  1670.                 if (!UniQueryChar(unis[0], CT_CNTRL)) {
  1671.                     rc = GpiSetCurrentPosition(prhps, &point);
  1672.                     rc = GpiCharString(prhps, len, charbuf);
  1673.                 }
  1674.                 uni[i] = unis[0];
  1675.             }
  1676.         }
  1677.  
  1678.         /*
  1679.          * Move to next character
  1680.          */
  1681.         point.x += tabSize;
  1682.         if ((i&0x0f) == 0x0f) {
  1683.             point.x = leftPos;
  1684.             point.y -= lineSize;
  1685.         }
  1686.     }
  1687.  
  1688.     /*
  1689.      * Put in the annotations
  1690.      */
  1691.     if (showuni) {
  1692.  
  1693.         /*
  1694.          * Set up the font and position
  1695.          */
  1696.         GpiSetCharSet(prhps, 1);
  1697.         GpiSetCp(prhps, 850);
  1698.         cbox.cx = MAKEFIXED(100, 0);
  1699.         cbox.cy = MAKEFIXED(100, 0);
  1700.         GpiSetCharBox(prhps, &cbox);
  1701.         point.y = topPos - lineSize - lineOffset + 26;
  1702.         point.x = leftPos + ((showuni==1) ? 190 : 0);
  1703.  
  1704.         /*
  1705.          * Put out annotation for each character with a unicode map
  1706.          */
  1707.         for (i=0; i<256; i++) {
  1708.             if (uni[i]) {
  1709.                 if (showuni==2) {
  1710.                     getglyph(uni[i]);
  1711.                     if (*GlyphIBM) {
  1712.                         strcpy(charbuf, GlyphIBM);
  1713.                         strupr(charbuf);
  1714.                     } else {
  1715.                         if (UniQueryChar(uni[i], CT_CNTRL)) {
  1716.                             *charbuf = 0;
  1717.                         } else {
  1718.                             sprintf(charbuf, "U000%04X", uni[i]);
  1719.                         }
  1720.                     }
  1721.                 } else {
  1722.                     sprintf(charbuf, "%04X", uni[i]);
  1723.                 }
  1724.                 rc = GpiSetCurrentPosition(prhps, &point);
  1725.                 rc = GpiCharString(prhps, strlen(charbuf), charbuf);
  1726.             }
  1727.  
  1728.             /*
  1729.              * Move to next character
  1730.              */
  1731.             point.x += tabSize;
  1732.             if ((i&0x0f) == 0x0f) {
  1733.                 point.x = leftPos + ((showuni==1) ? 190 : 0);
  1734.                 point.y -= lineSize;
  1735.             }
  1736.         }
  1737.     }
  1738.  
  1739.  
  1740.     DevEscape( prhdc, DEVESC_ENDDOC,
  1741.                0L, (PBYTE)NULL, (PLONG)NULL, (PBYTE)NULL );
  1742.  
  1743.     /*
  1744.      * Release and destroy the PS
  1745.      */
  1746.     GpiAssociate( prhps, (HDC)NULLHANDLE );
  1747.     GpiDestroyPS( prhps );
  1748.  
  1749.     /*
  1750.      * Inform the user we are done
  1751.      */
  1752.     DosBeep(1000, 200);
  1753. }
  1754.  
  1755.  
  1756. /**************************************************************************
  1757.  *
  1758.  *  Name       : UpdateTitleText
  1759.  *
  1760.  *  Description: Updates the text in the main window's title bar to
  1761.  *               display the app name, followed by the separator,
  1762.  *               followed by the file name.
  1763.  *
  1764.  *  Concepts :   Called at init time and when the text file is changed.
  1765.  *               Gets the program name, appends the separator, and
  1766.  *               appends the file name.
  1767.  *
  1768.  *  API's      : WinLoadString
  1769.  *               WinSetWindowText
  1770.  *               WinWindowFromID
  1771.  *
  1772.  *  Parameters : hwnd = window handle
  1773.  *
  1774.  *  Return     :  [none]
  1775.  *
  1776.  *************************************************************************/
  1777. VOID UpdateTitleText(HWND hwnd)
  1778. {
  1779.    CHAR szBuf[256];
  1780.    CHAR szSeparator[TITLESEPARATORLEN+1];
  1781.    char codepg[16];
  1782.    PSZ pszT;
  1783.    ULONG codepage;
  1784.  
  1785.    WinLoadString(hab, (HMODULE)0, IDS_CODEPAGE, MAXNAMEL, szBuf);
  1786.    WinLoadString(hab, (HMODULE)0, IDS_TITLEBARSEPARATOR, TITLESEPARATORLEN, szSeparator);
  1787.  
  1788.    itoa(Codepage, codepg, 10);
  1789.    strcat(szBuf, codepg);
  1790.    if (InWard) {
  1791.        sprintf(codepg, "[%02x]", Ward);
  1792.        strcat(szBuf, codepg);
  1793.    }
  1794.    if (*CodeName) {
  1795.        strcat(szBuf, szSeparator);
  1796.        strcat(szBuf, CodeName);
  1797.    }
  1798.    strcat(szBuf, szSeparator);
  1799.    if (Font) {
  1800.        strcat(szBuf, Font);
  1801.    }
  1802.  
  1803.    WinSetWindowText(WinWindowFromID(hwnd, FID_TITLEBAR), szBuf);
  1804. }   /* End of UpdateTitleText   */
  1805.  
  1806.  
  1807. /**************************************************************************
  1808.  *
  1809.  *  Name       : ProductInfoDlgProc(hwnd, msg, mp1, mp2)
  1810.  *
  1811.  *  Description: Processes all messages sent to the Product information
  1812.  *               dialog
  1813.  *
  1814.  *  Concepts:  The Product information dialog has only a button control,
  1815.  *             so this routine processes only WM_COMMAND messages.  Any
  1816.  *             WM_COMMAND posted must have come from the OK
  1817.  *             button, so we dismiss the dialog upon receiving it.
  1818.  *
  1819.  *  API's      :  WinDismissDlg
  1820.  *                WinDefDlgProc
  1821.  *
  1822.  *  Parameters :  hwnd     = window handle
  1823.  *                msg      = message i.d.
  1824.  *                mp1      = first message parameter
  1825.  *                mp2      = second message parameter
  1826.  *
  1827.  *  Return     :  dependent on message sent
  1828.  *
  1829.  *************************************************************************/
  1830. MRESULT EXPENTRY ProductInfoDlgProc(
  1831.                          HWND hwnd,      /* handle of window */
  1832.                          USHORT msg,     /* id of message */
  1833.                          MPARAM mp1,     /* first message parameter */
  1834.                          MPARAM mp2)     /* second message parameter */
  1835. {
  1836.    switch(msg)
  1837.    {
  1838.       case WM_INITDLG:
  1839.          SetSysMenu(hwnd);       /* system menu for this dialog  */
  1840.          return MRFROMSHORT(FALSE);
  1841.  
  1842.       case WM_COMMAND:
  1843.            /* no matter what the command, close the dialog */
  1844.          WinDismissDlg(hwnd, TRUE);
  1845.          break;
  1846.  
  1847.       default:
  1848.          return(WinDefDlgProc(hwnd, msg, mp1, mp2));
  1849.          break;
  1850.    }
  1851.    return (MRESULT)NULL;
  1852. }   /*  End of ProductInfoDlgProc   */
  1853.  
  1854.  
  1855. /**************************************************************************
  1856.  *
  1857.  *  Name       : SetSysMenu(hDlg)
  1858.  *
  1859.  *  Description: Sets only the Move and Close items of the system menu
  1860.  *
  1861.  *  Concepts:  Any dialog box is free to call this routine, to edit
  1862.  *             which menu items will appear on its System Menu pulldown.
  1863.  *
  1864.  *  API's      :  WinWindowFromID
  1865.  *                WinSendMsg
  1866.  *
  1867.  *  Parameters :  hDlg     = window handle of the dialog
  1868.  *
  1869.  *  Return     :  [none]
  1870.  *
  1871.  *************************************************************************/
  1872. VOID SetSysMenu(HWND hDlg)
  1873. {
  1874.     HWND     hSysMenu;
  1875.     MENUITEM Mi;
  1876.     ULONG    Pos;
  1877.     MRESULT  Id;
  1878.     SHORT    cItems;
  1879.  
  1880.     /******************************************************************/
  1881.     /*  We only want Move and Close in the system menu.               */
  1882.     /******************************************************************/
  1883.  
  1884.     hSysMenu = WinWindowFromID(hDlg, FID_SYSMENU);
  1885.     WinSendMsg( hSysMenu, MM_QUERYITEM
  1886.               , MPFROM2SHORT(SC_SYSMENU, FALSE), MPFROMP((PCH) & Mi));
  1887.     Pos = 0L;
  1888.     cItems = (SHORT)WinSendMsg( Mi.hwndSubMenu, MM_QUERYITEMCOUNT,
  1889.                                 (MPARAM)NULL, (MPARAM)NULL);
  1890.     while (cItems--)
  1891.     {
  1892.         Id = WinSendMsg( Mi.hwndSubMenu, MM_ITEMIDFROMPOSITION
  1893.                           , MPFROMLONG(Pos), (MPARAM)NULL);
  1894.         switch (SHORT1FROMMR(Id))
  1895.         {
  1896.         case SC_MOVE:
  1897.         case SC_CLOSE:
  1898.             Pos++;  /* Don't delete that one. */
  1899.             break;
  1900.         default:
  1901.             WinSendMsg( Mi.hwndSubMenu, MM_DELETEITEM
  1902.                       , MPFROM2SHORT((USHORT)Id, TRUE), (MPARAM)NULL);
  1903.         }
  1904.     }
  1905. }   /*  End of SetSysMenu  */
  1906.  
  1907.  
  1908. /**************************************************************************
  1909.  *
  1910.  *  Name       : EditUndo(mp2)
  1911.  *
  1912.  *  Description: Processes selection of the Undo choice of the Edit
  1913.  *               pulldown
  1914.  *
  1915.  *  Concepts:  called whenever Undo from the Edit menu is selected
  1916.  *
  1917.  *  API's      :  [none]
  1918.  *
  1919.  *  Parameters :  mp2      = second message parameter
  1920.  *
  1921.  *  Return     :  [none]
  1922.  *
  1923.  *************************************************************************/
  1924. VOID EditUndo(MPARAM mp2)
  1925. {
  1926.     /* This routine currently doesn't use the mp2 parameter but
  1927.      *  it is referenced here to prevent an 'Unreferenced Parameter'
  1928.      *  warning at compile time.
  1929.      */
  1930.     mp2;
  1931. }   /* End of EditUndo   */
  1932.  
  1933. /**************************************************************************
  1934.  *
  1935.  *  Name       : EditCut(mp2)
  1936.  *
  1937.  *  Description: Processes selection of the Cut choice of the Edit
  1938.  *               pulldown
  1939.  *
  1940.  *  Concepts:  called whenever Cut from the Edit menu is selected
  1941.  *
  1942.  *  API's      :  [none]
  1943.  *
  1944.  *  Parameters :  mp2      = second message parameter
  1945.  *
  1946.  *  Return     :  [none]
  1947.  *
  1948.  *************************************************************************/
  1949. VOID EditCut(MPARAM mp2)
  1950. {
  1951.     /* This routine currently doesn't use the mp2 parameter but
  1952.      *  it is referenced here to prevent an 'Unreferenced Parameter'
  1953.      *  warning at compile time.
  1954.      */
  1955.     mp2;
  1956. }   /* End of EditCut   */
  1957.  
  1958. /**************************************************************************
  1959.  *
  1960.  *  Name       : EditCopy(mp2)
  1961.  *
  1962.  *  Description: Processes selection of the Copy choice of the Edit
  1963.  *               pulldown
  1964.  *
  1965.  *  Concepts:  called whenever Copy from the Edit menu is selected
  1966.  *
  1967.  *  API's      :  [none]
  1968.  *
  1969.  *  Parameters :  mp2      = second message parameter
  1970.  *
  1971.  *  Return     :  [none]
  1972.  *
  1973.  *************************************************************************/
  1974. VOID EditCopy(MPARAM mp2)
  1975. {
  1976.     /* This routine currently doesn't use the mp2 parameter but
  1977.      *  it is referenced here to prevent an 'Unreferenced Parameter'
  1978.      *  warning at compile time.
  1979.      */
  1980.     mp2;
  1981. }   /* End of EditCopy   */
  1982.  
  1983. /**************************************************************************
  1984.  *
  1985.  *  Name       : EditPaste(mp2)
  1986.  *
  1987.  *  Description: Processes selection of the Paste choice of the Edit
  1988.  *               pulldown
  1989.  *
  1990.  *  Concepts:  called whenever Paste from the Edit menu is selected
  1991.  *
  1992.  *  API's      :  [none]
  1993.  *
  1994.  *  Parameters :  mp2      = second message parameter
  1995.  *
  1996.  *  Return     :  [none]
  1997.  *
  1998.  *************************************************************************/
  1999. VOID EditPaste(MPARAM mp2)
  2000. {
  2001.     /* This routine currently doesn't use the mp2 parameter but
  2002.      *  it is referenced here to prevent an 'Unreferenced Parameter'
  2003.      *  warning at compile time.
  2004.      */
  2005.     mp2;
  2006. }   /* End of EditPaste    */
  2007.  
  2008. /**************************************************************************
  2009.  *
  2010.  *  Name       : EditClear(mp2)
  2011.  *
  2012.  *  Description: Processes selection of the Clear choice of the Edit
  2013.  *               pulldown
  2014.  *
  2015.  *  Concepts:  called whenever Clear from the Edit menu is selected
  2016.  *
  2017.  *  API's      :  [none]
  2018.  *
  2019.  *  Parameters :  mp2      = second message parameter
  2020.  *
  2021.  *  Return     :  [none]
  2022.  *
  2023.  *************************************************************************/
  2024. VOID EditClear(MPARAM mp2)
  2025. {
  2026.     /* This routine currently doesn't use the mp2 parameter but
  2027.      *  it is referenced here to prevent an 'Unreferenced Parameter'
  2028.      *  warning at compile time.
  2029.      */
  2030.     mp2;
  2031. }   /* End of EditClear   */
  2032.  
  2033.  
  2034.  
  2035. /**************************************************************************
  2036.  *
  2037.  *  Name       : InitMenu()
  2038.  *
  2039.  *  Description: Processes the WM_INITMENU message for the main window,
  2040.  *               disabling any menus that are not active.
  2041.  *
  2042.  *  Concepts:    Routine is called each time a menu is dropped.
  2043.  *
  2044.  *               A switch statement branches control based upon
  2045.  *               the id of the menu that is being displayed.
  2046.  *
  2047.  *  API's      :  [none]
  2048.  *
  2049.  *  Parameters :  mp1  = first message parameter
  2050.  *                mp2  = second message parameter
  2051.  *
  2052.  *  Return     :  [none]
  2053.  *
  2054.  *************************************************************************/
  2055. VOID InitMenu(MPARAM mp1, MPARAM mp2)
  2056. {
  2057.               /* define a shorthand way of denoting the menu handle */
  2058. #define hwndMenu        HWNDFROMMP(mp2)
  2059.  
  2060.    switch(SHORT1FROMMP(mp1))
  2061.    {
  2062.    case IDM_FILE:
  2063.       break;
  2064.  
  2065.    case IDM_HELP:
  2066.             /*
  2067.              * Enable or disable the Help menu depending upon whether the
  2068.              * help manager has been enabled
  2069.              */
  2070.         EnableMenuItem(hwndMenu, IDM_HELPUSINGHELP, fHelpEnabled);
  2071.         EnableMenuItem(hwndMenu, IDM_HELPGENERAL, fHelpEnabled);
  2072.         EnableMenuItem(hwndMenu, IDM_HELPKEYS, fHelpEnabled);
  2073.         EnableMenuItem(hwndMenu, IDM_HELPINDEX, fHelpEnabled);
  2074.  
  2075.          /*  REMEMBER: add a case for IDM_HELPTUTORIAL if you include
  2076.           *  the Tutorial menu item.
  2077.           */
  2078.  
  2079.        break;
  2080.  
  2081.     default:
  2082.        break;
  2083.     }
  2084.  
  2085. #undef hwndMenu
  2086. }   /* End of InitMenu   */
  2087.  
  2088. /**************************************************************************
  2089.  *
  2090.  *  Name       : EnableMenuItem(hwndMenu, idItem, fEnable)
  2091.  *
  2092.  *  Description: Enables or disables the menu item
  2093.  *
  2094.  *  Concepts:    Called whenever a menu item is to be enabled or
  2095.  *               disabled
  2096.  *
  2097.  *               Sends a MM_SETITEMATTR to the menu with the
  2098.  *               given item id.  Sets the MIA_DISABLED attribute
  2099.  *               flag if the item is to be disabled, clears the flag
  2100.  *               if enabling.
  2101.  *
  2102.  *  API's      : WinSendMsg
  2103.  *
  2104.  *  Parameters :  hwndmenu = menu window handle
  2105.  *                idItem   = menu item i.d.
  2106.  *                fEnable  = enable (yes) or disable (no)
  2107.  *
  2108.  *  Return     :  [none]
  2109.  *
  2110.  *************************************************************************/
  2111. VOID EnableMenuItem(HWND hwndMenu, USHORT idItem, BOOL fEnable)
  2112. {
  2113.    SHORT fsFlag;
  2114.  
  2115.    if(fEnable)
  2116.       fsFlag = 0;
  2117.    else
  2118.       fsFlag = MIA_DISABLED;
  2119.  
  2120.    WinSendMsg(hwndMenu,
  2121.               MM_SETITEMATTR,
  2122.               MPFROM2SHORT(idItem, TRUE),
  2123.               MPFROM2SHORT(MIA_DISABLED, fsFlag));
  2124.  
  2125. }   /* End of EnableMenuItem() */
  2126. /***************************  End of user.c  ****************************/
  2127.  
  2128.  
  2129. /**************************************************************************
  2130.  *
  2131.  *  Name       : Init()
  2132.  *
  2133.  *  Description:  Performs initialization functions required
  2134.  *                before the main window can be created.
  2135.  *
  2136.  *  Concepts:     Called once before the main window is created.
  2137.  *
  2138.  *                - Installs the routine ExitProc into the
  2139.  *                  DosExitList chain
  2140.  *                - registers all window classes
  2141.  *                - performs any command line processing
  2142.  *
  2143.  *  API's      :  DosExitList
  2144.  *                DosExit
  2145.  *                WinLoadString
  2146.  *                WinRegisterClass
  2147.  *
  2148.  *  Parameters :  [none]
  2149.  *
  2150.  *  Return     :  TRUE = initialization is successful
  2151.  *                FALSE = initialization failed
  2152.  *
  2153.  *************************************************************************/
  2154. BOOL Init(VOID)
  2155. {
  2156.  
  2157.    /* Add ExitProc to the exit list to handle the exit processing.  If
  2158.     * there is an error, then terminate the process since there have
  2159.     * not been any resources allocated yet.
  2160.     */
  2161.    if(DosExitList(EXLST_ADD, (PFNEXITLIST)ExitProc))
  2162.    {
  2163.       MessageBox(HWND_DESKTOP,
  2164.                  IDMSG_CANNOTLOADEXITLIST,
  2165.                  MB_OK | MB_ERROR,
  2166.                  TRUE);
  2167.       DosExit(EXIT_PROCESS, RETURN_ERROR);
  2168.    }
  2169.  
  2170.    /* load application name from resource file */
  2171.    if(0 == WinLoadString(hab, (HMODULE)0, IDS_APPNAME, MAXNAMEL, szAppName))
  2172.       return FALSE;
  2173.  
  2174.    /* register the main client window class */
  2175.    if(!WinRegisterClass(hab,
  2176.                        (PSZ)szAppName,
  2177.                        (PFNWP)MainWndProc,
  2178.                        CS_SIZEREDRAW | CS_CLIPCHILDREN,
  2179.                        0L))
  2180.        return FALSE;
  2181.  
  2182.    /* If you wish to create a thread for background processing, define
  2183.     *  the BACKGROUND_THREAD constant
  2184.     *  the routine commented out here.  The routines for the background
  2185.     *  thread are in the thrd.c file.
  2186.     */
  2187.    return TRUE;
  2188. }  /* End of Init   */
  2189.  
  2190. /**************************************************************************
  2191.  *
  2192.  *  Name       : InitMainWindow(hwnd, mp1, mp2)
  2193.  *
  2194.  *  Description: Performs initialization functions required
  2195.  *               when the main window is created.
  2196.  *
  2197.  *  Concepts:    Called once during the WM_CREATE processing when
  2198.  *               the main window is created.
  2199.  *
  2200.  *  API's      : [none]
  2201.  *
  2202.  *  Parameters :  hwnd = window handle
  2203.  *                mp1  = first message parameter
  2204.  *                mp2  = second message parameter
  2205.  *
  2206.  *  Return     :   value to be returned from the WM_CREATE message:
  2207.  *                TRUE =  window creation should stop
  2208.  *                FALSE = window creation should continue
  2209.  *
  2210.  *************************************************************************/
  2211. MRESULT InitMainWindow(HWND hwnd, MPARAM mp1, MPARAM mp2)
  2212. {
  2213.     char fontname[128];
  2214.     HWND hwndParent;
  2215.  
  2216.     hwndParent = ((PCREATESTRUCT)PVOIDFROMMP(mp2))->hwndParent;
  2217.     UpdateTitleText(hwndParent);
  2218.  
  2219.    /* return FALSE to continue window creation, TRUE to abort it */
  2220.    return (MRESULT)FALSE;
  2221.  
  2222.  
  2223.    /* This routine currently doesn't use the hwnd, mp1, and mp2 parameters
  2224.     *  so they are referenced here to prevent an 'Unreferenced Parameter'
  2225.     *  warning at compile time.
  2226.     */
  2227.  
  2228.    hwnd;
  2229.    mp1;
  2230.    mp2;
  2231. }   /* End of InitMainWindow   */
  2232.  
  2233.  
  2234. /**************************************************************************
  2235.  *
  2236.  *  Name       : ExitProc(usTermCode)
  2237.  *
  2238.  *  Description: Cleans up certain resources when the application
  2239.  *               terminates.
  2240.  *
  2241.  *  Concepts:    Routine is called by DosExitList when the
  2242.  *               application exits.
  2243.  *
  2244.  *               Global resources, such as the main window and
  2245.  *               message queue, are destroyed and any system
  2246.  *               resources used are freed.
  2247.  *
  2248.  *  API's      : WinIsWindow
  2249.  *               WinDestroyWindow
  2250.  *               WinDestroyMsgQueue
  2251.  *               WinTerminate
  2252.  *               DosExitList
  2253.  *
  2254.  *  Parameters :  usTermCode = termination code number
  2255.  *
  2256.  *  Return    :   Returns EXLST_EXIT to the DosExitList handler
  2257.  *
  2258.  *************************************************************************/
  2259. VOID ExitProc(USHORT usTermCode) {
  2260.     /*
  2261.      * destroy the main window if it exists
  2262.      */
  2263.     if (WinIsWindow(hab, hwndMainFrame))
  2264.         WinDestroyWindow(hwndMainFrame);
  2265.  
  2266.     WinDestroyMsgQueue(hmq);
  2267.  
  2268.     WinTerminate(hab);
  2269.  
  2270.     DosExitList(EXLST_EXIT, (PFNEXITLIST)NULL);    /* termination complete */
  2271.  
  2272.  
  2273.     /* This routine currently doesn't use the usTermCode parameter so
  2274.      *  it is referenced here to prevent an 'Unreferenced Parameter'
  2275.      *  warning at compile time
  2276.      */
  2277.  
  2278. usTermCode;
  2279. }
  2280.  
  2281. #define HELPLIBRARYNAMELEN  20
  2282.  
  2283. /* If DEBUG is defined, then the help panels will display their
  2284.  *  id values on their title bar.  This is useful for determining
  2285.  *  which help panels are being shown for each dialog item.  When
  2286.  *  the DEBUG directive is not defined, then the panel ids are not
  2287.  *  displayed.
  2288.  */
  2289.  
  2290. /* #define  DEBUG */
  2291.  
  2292. /*
  2293.  *  Global variables
  2294.  */
  2295. static HWND hwndHelpInstance;
  2296. static CHAR szLibName[HELPLIBRARYNAMELEN];
  2297. static CHAR szWindowTitle[HELPLIBRARYNAMELEN];
  2298.  
  2299. /**************************************************************************
  2300.  *
  2301.  *  Name       : InitHelp()
  2302.  *
  2303.  *  Description:  Initializes the IPF help facility
  2304.  *
  2305.  *  Concepts:     Called once during initialization of the program
  2306.  *
  2307.  *                Initializes the HELPINIT structure and creates the
  2308.  *                help instance.  If successful, the help instance
  2309.  *                is associated with the main window.
  2310.  *
  2311.  *  API's      :  WinLoadString
  2312.  *                WinCreateHelpInstance
  2313.  *                WinAssociateHelpInstance
  2314.  *
  2315.  *  Parameters :  [none]
  2316.  *
  2317.  *  Return     :  [none]
  2318.  *
  2319.  *************************************************************************/
  2320. VOID InitHelp(VOID) {
  2321.    HELPINIT hini;
  2322.  
  2323.    /* if we return because of an error, Help will be disabled */
  2324.    fHelpEnabled = FALSE;
  2325.  
  2326.    /* initialize help init structure */
  2327.    hini.cb = sizeof(HELPINIT);
  2328.    hini.ulReturnCode = 0;
  2329.  
  2330.    hini.pszTutorialName = (PSZ)NULL;   /* if tutorial added, add name here */
  2331.  
  2332.    hini.phtHelpTable = (PHELPTABLE)MAKELONG(TEMPLATE_HELP_TABLE, 0xFFFF);
  2333.    hini.hmodHelpTableModule = 0;
  2334.    hini.hmodAccelActionBarModule = 0;
  2335.    hini.idAccelTable = 0;
  2336.    hini.idActionBar = 0;
  2337.  
  2338.    if(!WinLoadString(hab,
  2339.                      (HMODULE)0,
  2340.                      IDS_HELPWINDOWTITLE,
  2341.                      HELPLIBRARYNAMELEN,
  2342.                      (PSZ)szWindowTitle))
  2343.    {
  2344.       MessageBox(hwndMain, IDMSG_CANNOTLOADSTRING, MB_OK | MB_ERROR, FALSE);
  2345.       return;
  2346.    }
  2347.  
  2348.    hini.pszHelpWindowTitle = (PSZ)szWindowTitle;
  2349.  
  2350.    /* if debugging, show panel ids, else don't */
  2351. #ifdef DEBUG
  2352.    hini.fShowPanelId = CMIC_SHOW_PANEL_ID;
  2353. #else
  2354.    hini.fShowPanelId = CMIC_HIDE_PANEL_ID;
  2355. #endif
  2356.  
  2357.    if(!WinLoadString(hab,
  2358.                      (HMODULE)0,
  2359.                      IDS_HELPLIBRARYNAME,
  2360.                      HELPLIBRARYNAMELEN,
  2361.                      (PSZ)szLibName))
  2362.    {
  2363.       MessageBox(hwndMain, IDMSG_CANNOTLOADSTRING, MB_OK | MB_ERROR, FALSE);
  2364.       return;
  2365.    }
  2366.  
  2367.    hini.pszHelpLibraryName = (PSZ)szLibName;
  2368.  
  2369.    /* creating help instance */
  2370.    hwndHelpInstance = WinCreateHelpInstance(hab, &hini);
  2371.  
  2372.    if(hwndHelpInstance == NULLHANDLE || hini.ulReturnCode)
  2373.    {
  2374.       MessageBox(hwndMainFrame, IDMSG_HELPLOADERROR, MB_OK | MB_ERROR, TRUE);
  2375.       return;
  2376.    }
  2377.  
  2378.    /* associate help instance with main frame */
  2379.    if(!WinAssociateHelpInstance(hwndHelpInstance, hwndMainFrame))
  2380.    {
  2381.       MessageBox(hwndMainFrame, IDMSG_HELPLOADERROR, MB_OK | MB_ERROR, TRUE);
  2382.       return;
  2383.    }
  2384.  
  2385.    /* help manager is successfully initialized so set flag to TRUE */
  2386.    fHelpEnabled = TRUE;
  2387. }   /* End of InitHelp   */
  2388.  
  2389.  
  2390. /**************************************************************************
  2391.  *
  2392.  *  Name       : HelpGeneral()
  2393.  *
  2394.  *  Description: Processes the WM_COMMAND message posted by the
  2395.  *               General Help item of the Help menu.
  2396.  *
  2397.  *  Concepts:    Called from MainCommand when the General Help
  2398.  *               menu item is selected.
  2399.  *
  2400.  *               Sends an HM_EXT_HELP message to the help
  2401.  *               instance so that the default Extended Help is
  2402.  *               displayed.
  2403.  *
  2404.  *  API's      : WinSendMsg
  2405.  *
  2406.  *  Parameters :  [none]
  2407.  *
  2408.  *  Return     :  [none]
  2409.  *
  2410.  *************************************************************************/
  2411. VOID  HelpGeneral(VOID)
  2412. {
  2413.     /* this just displays the system extended help panel */
  2414.    if(fHelpEnabled)
  2415.       if(NULL != WinSendMsg(hwndHelpInstance, HM_EXT_HELP,
  2416.                             (MPARAM)NULL, (MPARAM)NULL))
  2417.          MessageBox(hwndMain,
  2418.                     IDMSG_HELPDISPLAYERROR,
  2419.                     MB_OK | MB_ERROR,
  2420.                     FALSE);
  2421. }   /* End of HelpGeneral  */
  2422.  
  2423. /**************************************************************************
  2424.  *
  2425.  *  Name       : HelpUsingHelp()
  2426.  *
  2427.  *  Description: Processes the WM_COMMAND message posted by the
  2428.  *               Using Help item of the Help menu.
  2429.  *
  2430.  *  Concepts:    Called from MainCommand when the Using Help
  2431.  *               menu item is selected.
  2432.  *
  2433.  *               Sends an HM_DISPLAY_HELP message to the help
  2434.  *               instance so that the default Using Help is
  2435.  *               displayed.
  2436.  *
  2437.  *  API's      : WinSendMsg
  2438.  *
  2439.  *  Parameters :  [none]
  2440.  *
  2441.  *  Return     :  [none]
  2442.  *
  2443.  *************************************************************************/
  2444. VOID  HelpUsingHelp(VOID)
  2445. {
  2446.    /* this just displays the system help for help panel */
  2447.    if(fHelpEnabled)
  2448.       if(NULL != WinSendMsg(hwndHelpInstance, HM_DISPLAY_HELP,
  2449.                             (MPARAM)NULL, (MPARAM)NULL))
  2450.          MessageBox(hwndMain,
  2451.                     IDMSG_HELPDISPLAYERROR,
  2452.                     MB_OK | MB_ERROR,
  2453.                     FALSE);
  2454. }   /* End of HelpUsingHelp   */
  2455.  
  2456.  
  2457. /**************************************************************************
  2458.  *
  2459.  *  Name       : HelpKeys()
  2460.  *
  2461.  *  Description: Processes the WM_COMMAND message posted by the
  2462.  *               Keys Help item of the Help menu.
  2463.  *
  2464.  *  Concepts:    Called from MainCommand when the Keys Help
  2465.  *               menu item is selected.
  2466.  *
  2467.  *               Sends an HM_KEYS_HELP message to the help
  2468.  *               instance so that the default Keys Help is
  2469.  *               displayed.
  2470.  *
  2471.  *  API's      : WinSendMsg
  2472.  *
  2473.  *  Parameters :  [none]
  2474.  *
  2475.  *  Return     :  [none]
  2476.  *
  2477.  *************************************************************************/
  2478. VOID  HelpKeys(VOID)
  2479. {
  2480.    /* this just displays the system keys help panel */
  2481.    if(fHelpEnabled)
  2482.       if(NULL != WinSendMsg(hwndHelpInstance, HM_KEYS_HELP,
  2483.                             (MPARAM)NULL, (MPARAM)NULL))
  2484.          MessageBox(hwndMain,
  2485.                     IDMSG_HELPDISPLAYERROR,
  2486.                     MB_OK | MB_ERROR,
  2487.                     FALSE);
  2488. }   /* End of HelpKeys   */
  2489.  
  2490.  
  2491. /**************************************************************************
  2492.  *
  2493.  *  Name       : HelpIndex()
  2494.  *
  2495.  *  Description: Processes the WM_COMMAND message posted by the
  2496.  *               Help Index item of the Help menu.
  2497.  *
  2498.  *  Concepts:    Called from MainCommand when the Help Index
  2499.  *               menu item is selected.
  2500.  *
  2501.  *               Sends an HM_INDEX_HELP message to the help
  2502.  *               instance so that the default Help Index is
  2503.  *               displayed.
  2504.  *
  2505.  *  API's      : WinSendMsg
  2506.  *
  2507.  *  Parameters :  [none]
  2508.  *
  2509.  *  Return     :  [none]
  2510.  *
  2511.  *************************************************************************/
  2512. VOID  HelpIndex(VOID)
  2513. {
  2514.    /* this just displays the system help index panel */
  2515.    if(fHelpEnabled)
  2516.       if(NULL != WinSendMsg(hwndHelpInstance, HM_HELP_INDEX,
  2517.                              (MPARAM)NULL, (MPARAM)NULL))
  2518.          MessageBox(hwndMain,
  2519.                     IDMSG_HELPDISPLAYERROR,
  2520.                     MB_OK | MB_ERROR,
  2521.                     FALSE);
  2522. }   /* End of HelpIndex() */
  2523.  
  2524.  
  2525. /**************************************************************************
  2526.  *
  2527.  *  Name       : HelpTutorial()
  2528.  *
  2529.  *  Description: Processes the WM_COMMAND message posted by the
  2530.  *                Tutorial Help item of the Help menu.  While the
  2531.  *                standard template application does not include a
  2532.  *                Tutorial menu item, you can add one if your
  2533.  *                application has a tutorial.
  2534.  *
  2535.  *  Concepts:    Called from MainCommand when the Tutorial Help
  2536.  *               menu item is selected.
  2537.  *
  2538.  *  API's      :  WinLoadMessage
  2539.  *                WinMessageBox
  2540.  *                WinAlarm
  2541.  *
  2542.  *  Parameters :  [none]
  2543.  *
  2544.  *  Return     :  [none]
  2545.  *
  2546.  *************************************************************************/
  2547. VOID  HelpTutorial(VOID)
  2548. {
  2549.    CHAR szText[MESSAGELEN];
  2550.  
  2551.    /*
  2552.     *  Insert code for any tutorial below in place of the message box.
  2553.     */
  2554.    if(!WinLoadMessage(hab,
  2555.                      (HMODULE)NULLHANDLE,
  2556.                      IDMSG_YOURTUTORIAL,
  2557.                      MESSAGELEN,
  2558.                      (PSZ)szText))
  2559.    {
  2560.       WinAlarm(HWND_DESKTOP, WA_ERROR);
  2561.       return;
  2562.    }
  2563.    WinMessageBox(HWND_DESKTOP,
  2564.                  hwndMain,
  2565.                  szText,
  2566.                  "Tutorial",
  2567.                  MB_OK | MB_INFORMATION,
  2568.                  FALSE);
  2569.  
  2570. }   /* End of HelpTutorial   */
  2571.  
  2572.  
  2573. /**************************************************************************
  2574.  *
  2575.  *  Name       : HelpProductInfo()
  2576.  *
  2577.  *  Description: Processes the WM_COMMAND message posted by the
  2578.  *               Product information item of the Help Menu.
  2579.  *
  2580.  *  Concepts:    Called from MainCommand when the Product information
  2581.  *               menu item is selected
  2582.  *
  2583.  *               Calls WinDlgBox to display the Product information dialog.
  2584.  *
  2585.  *  API's      : WinDlgBox
  2586.  *
  2587.  *  Parameters :  [none]
  2588.  *
  2589.  *  Return     :  [none]
  2590.  *
  2591.  *************************************************************************/
  2592. VOID  HelpProductInfo(VOID)
  2593. {
  2594.    /* display the Product Information dialog. */
  2595.    WinDlgBox(HWND_DESKTOP,
  2596.              hwndMain,
  2597.              (PFNWP)ProductInfoDlgProc,
  2598.              0,
  2599.              IDD_PRODUCTINFO,
  2600.              (PVOID)NULL);
  2601. }   /* End of HelpProductInfo() */
  2602.  
  2603.  
  2604. /**************************************************************************
  2605.  *
  2606.  *  Name       : DisplayHelpPanel(idPanel)
  2607.  *
  2608.  *  Description: Displays the help panel whose id is given
  2609.  *
  2610.  *  Concepts:    Called whenever a help panel is desired to be
  2611.  *               displayed, usually from the WM_HELP processing
  2612.  *               of the dialog boxes.
  2613.  *
  2614.  *               Sends HM_DISPLAY_HELP message to the help instance.
  2615.  *
  2616.  *  API's      : WinSendMsg
  2617.  *
  2618.  *  Parameters :  idPanel = panel i.d.
  2619.  *
  2620.  *  Return     :  [none]
  2621.  *
  2622.  *************************************************************************/
  2623. VOID DisplayHelpPanel(ULONG idPanel)
  2624. {
  2625.    if(fHelpEnabled)
  2626.       if(NULL != WinSendMsg(hwndHelpInstance,
  2627.                             HM_DISPLAY_HELP,
  2628.                             MPFROMLONG(idPanel),
  2629.                             MPFROMSHORT(HM_RESOURCEID)))
  2630.          MessageBox(hwndMainFrame,
  2631.                     IDMSG_HELPDISPLAYERROR,
  2632.                     MB_OK | MB_ERROR,
  2633.                     TRUE);
  2634. }   /* End of DisplayHelpPanel   */
  2635.  
  2636.  
  2637. /*
  2638.  * DestroyHelpInstance:
  2639.  */
  2640. VOID DestroyHelpInstance(VOID) {
  2641.    if (hwndHelpInstance)
  2642.        WinDestroyHelpInstance(hwndHelpInstance);
  2643. }
  2644.  
  2645.  
  2646. /*
  2647.  * getglyph:  Get the glyph name in IBM and Adobe styles
  2648.  */
  2649. int  getglyph(UniChar uni) {
  2650.     NAMETAB * np;
  2651.  
  2652.     GlyphIBM[0] = 0;
  2653.     GlyphAdobe[0] = 0;
  2654.     if (!Unitext) {
  2655.         if (getnames(&Unicode,  "unicode.nam",  &Unitext, Utab))
  2656.             Unitext = (char *)1;
  2657.     }
  2658.     if (Unitext == (char *)1)
  2659.         return 0;
  2660.  
  2661.     np = Utab[uni>>8];
  2662.     if (!np)
  2663.         return 0;
  2664.  
  2665.     while (np->name) {
  2666.         if (np->uni==uni) {
  2667.             if (np->len==8 && isdigit(np->name[6]) && isdigit(np->name[7])) {
  2668.                 strcpy(GlyphIBM, np->name);
  2669.                 strupr(GlyphIBM);
  2670.                 np++;
  2671.                 if (np->uni != uni)
  2672.                     return 1;
  2673.             }
  2674.             strcpy(GlyphAdobe, np->name);
  2675.             return 1;
  2676.         }
  2677.         np++;
  2678.     }
  2679.     return 0;
  2680. }
  2681.  
  2682.  
  2683. /*
  2684.  * getline: Get the line a remember it for an error message
  2685.  */
  2686. char * getline(char * buf, FILE * f) {
  2687.     char * ret;
  2688.     char * cp;
  2689.  
  2690.     *buf = 0;
  2691.     ret = fgets(buf, 255, f);
  2692.  
  2693.     /* Strip CR and LF from the end of the line */
  2694.     cp = buf+strlen(buf)-1;
  2695.     while (*cp=='\n' || *cp=='\r') {
  2696.         cp--;
  2697.     }
  2698.     cp[1]=0;
  2699.     cp[2]=0;
  2700.  
  2701.     strncpy(InLine, buf, 255);
  2702.     return ret;
  2703. }
  2704.  
  2705.  
  2706. /*
  2707.  *  getnames: Read in a name table.
  2708.  *            The file is read twice, once to get the sizes, and
  2709.  *            a second time to make the actual tables.
  2710.  *
  2711.  *  Notes:
  2712.  *      The code in this section is taken from the original code within
  2713.  *      makekb.  Several of the support routines came with it even though
  2714.  *      they are minimally used.
  2715.  */
  2716. int   getnames(NAMETAB * * tab, char * name, char * * text, NAMETAB * * utab) {
  2717.     FILE  * f;
  2718.     int     len;
  2719.     NAMETAB * np;
  2720.     char  * tp;
  2721.     char    line[256];
  2722.     long    val;
  2723.     long    entrycount;
  2724.     long    stringlen;
  2725.  
  2726.     f = findopen(name, "r", "PATH", 0);
  2727.     if (!f) return 1;
  2728.  
  2729.     entrycount = 0;
  2730.     stringlen  = 0;
  2731.  
  2732.  
  2733.     /*
  2734.      * Process one pass to find the sizes of stuff
  2735.      */
  2736.     line[255]=0;
  2737.     getline(line, f);
  2738.     while (!feof(f) && !ferror(f)) {
  2739.         if (*line!='*' && *line!=';' && *line!='#') {
  2740.             val = parse(line, &Value);
  2741.             nullword(Value);
  2742.             if (val && val<=0xffff) {
  2743.                 while (*Value && *Value!=';') {
  2744.                     entrycount++;
  2745.                     stringlen += (strlen(Value)+1);
  2746.                     Value = nexttoken(Value);
  2747.                 }
  2748.             } else {
  2749.                 if (val)
  2750.                     printf("Bad name entry - %s\n", InLine);
  2751.             }
  2752.         }
  2753.         getline(line, f);
  2754.     }
  2755.  
  2756.     if (ferror(f)) {
  2757.         printf("Error reading file - %s\n", name);
  2758.         return 2;
  2759.     }
  2760.  
  2761.     /*
  2762.      * Allocate the tables
  2763.      */
  2764.     entrycount++;
  2765.     stringlen += 8;
  2766.     *tab  = malloc(entrycount*sizeof(NAMETAB));
  2767.     *text = malloc(stringlen);
  2768.     np = *tab;
  2769.     tp = *text;
  2770.  
  2771.  
  2772.     /*
  2773.      * Process second pass to create the tables
  2774.      */
  2775.     rewind(f);
  2776.     getline(line, f);
  2777.     while (!feof(f) && !ferror(f)) {
  2778.         val = parse(line, &Value);
  2779.         nullword(Value);
  2780.         if (val && val<=0xffff) {
  2781.             while (*Value && *Value!=';') {
  2782.                 np->name = tp;
  2783.                 strcpy(tp, Value);
  2784.                 len = strlen(Value);
  2785.                 tp += (len+1);
  2786.                 np->len = len;
  2787.                 np->uni = val;
  2788.                 Value = nexttoken(Value);
  2789.                 if (!utab[val>>8]) {
  2790.                     utab[val>>8] = np;
  2791.                 }
  2792.                 np++;
  2793.             }
  2794.         }
  2795.         getline(line, f);
  2796.     }
  2797.     np->name = 0;
  2798.     np->uni = 0;
  2799.     np->len = 0;
  2800.  
  2801.     fclose(f);
  2802.     return 0;
  2803. }
  2804.  
  2805.  
  2806. /*
  2807.  *  parse:  Parse the input line
  2808.  */
  2809. long  parse (char * line, char * * value) {
  2810.     char * cp, * kp;
  2811.  
  2812.     /* Strip CR and LF from the end of the line */
  2813.     cp = line+strlen(line)-1;
  2814.     while (*cp=='\n' || *cp=='\r') {
  2815.         cp--;
  2816.     }
  2817.     cp[1]=0;
  2818.     cp[2]=0;
  2819.  
  2820.     *value = line;
  2821.     cp = line;
  2822.  
  2823.     /*
  2824.      * Skip leading spaces and detect comments
  2825.      */
  2826.     while (*cp==' ' || *cp=='\t')
  2827.         cp++;
  2828.     if (*cp=='*' || *cp==';' || *cp=='#' || *cp=='/' || *cp==0 || *cp==0x1a) {
  2829.         return 0;
  2830.     }
  2831.  
  2832.     /* Find the keyword */
  2833.     kp = cp;
  2834.     while (*cp && *cp!=' ' && *cp!='\t' && *cp!='=') {
  2835.         *cp = (char) tolower(*cp);
  2836.         cp++;
  2837.     }
  2838.     *cp++=0;                 /* Make keyword into string */
  2839.  
  2840.     /* Skip blanks and = after keyword */
  2841.     while (*cp==' ' || *cp=='\t') cp++;  /* Skip blanks after keyword */
  2842.     if (*cp=='=') {          /* If = found, skip it and trailing blank */
  2843.         cp++;
  2844.         if(*cp==' ' || *cp=='\t') cp++;
  2845.     }
  2846.     *value = cp;
  2847.  
  2848.     return gethexval(kp);
  2849. }
  2850.  
  2851.  
  2852. /*
  2853.  *  gethexval:  Get a hex number.  Convert a hex value with an optional
  2854.  *              leading 0x.
  2855.  */
  2856. long gethexval(char * cp) {
  2857.     long    val;
  2858.     char   gotone;
  2859.     char   ch;
  2860.  
  2861.     val = 0;
  2862.     gotone = 0;
  2863.     if (*cp=='0') {
  2864.         cp++;
  2865.         if (!*cp) return 0;
  2866.         if (*cp=='x') cp++;
  2867.     }
  2868.     while (*cp) {
  2869.         if (*cp>='0' && *cp<='9') {
  2870.             ch = *cp-'0';
  2871.         } else {
  2872.             if (*cp>='a' && *cp<='f') {
  2873.                 ch = *cp-'a'+10;
  2874.             } else {
  2875.                 if (*cp>='A' && *cp<='F') {
  2876.                     ch = *cp-'A'+10;
  2877.                 } else {
  2878.                     if (*cp == ';')
  2879.                         break;
  2880.                     return NOTHEXVAL;
  2881.                 }
  2882.             }
  2883.         }
  2884.         val *= 16;
  2885.         val += ch;
  2886.         gotone = 1;
  2887.         cp++;
  2888.     }
  2889.     if (!gotone)
  2890.         return NOTHEXVAL;
  2891.     return val;
  2892. }
  2893.  
  2894.  
  2895. /*
  2896.  *  nexttoken:  Set value to the next token
  2897.  */
  2898. char * nexttoken(char * value) {
  2899.     if (!*value) return value;
  2900.     value += strlen(value);
  2901.     value++;
  2902.     while (*value==' ' || *value=='\t') value++;
  2903.     nullword(value);
  2904.     return value;
  2905. }
  2906.  
  2907.  
  2908. /*
  2909.  *  nullword:  Put a null at the end of the word
  2910.  */
  2911. void nullword(char * cptr) {
  2912.     char * cp;
  2913.  
  2914.     cp = cptr;
  2915.     while (*cp>' ') cp++;
  2916.     *cp = 0;
  2917. }
  2918.  
  2919.  
  2920. /*
  2921.  *  findopen:  Common file open routine
  2922.  */
  2923. FILE * findopen(char * fname, char * mode, char * path, int msg) {
  2924.     FILE   * f;
  2925.  
  2926.     searchenv(fname, path, Fn);
  2927.     if (*Fn==0 && msg) {
  2928.         printf("File not found - %s\n", fname);
  2929.         return NULL;
  2930.     }
  2931.  
  2932.     f = fopen(Fn, mode);
  2933.     if (!f && msg) {
  2934.         printf("Unable to open file - %s\n", fname);
  2935.         return NULL;
  2936.     }
  2937.     return f;
  2938. }
  2939.  
  2940. #define PATHSEP '/'
  2941. /*
  2942.  * searchenv:  Search for file along paths from environment variable
  2943.  */
  2944. void  searchenv(const char *fname, const char *env_var, register char *path) {
  2945.     register char *p;
  2946.     register int c;
  2947.     char *env_p;
  2948.  
  2949.     /* Check for fully specified file name */
  2950.     if (*fname=='/' || *fname=='\\' || fname[1]==':') {
  2951.         if (access(fname, 0)==0) {
  2952.             strcpy(path, fname);
  2953.         } else {
  2954.             *path = 0;
  2955.         }
  2956.         return;
  2957.     }
  2958.  
  2959.     /* Check exists in current directory */
  2960.     if (access(fname, 0) == 0) {
  2961.         getcwd(path, 256);
  2962.         p = path + strlen(path);
  2963.         if (((c = *(p - 1)) != '/') && (c != '\\') && (c != ':')) {
  2964.             *p++ = PATHSEP;
  2965.             *p = 0;
  2966.         }
  2967.         strcat(path, fname);
  2968.         return;
  2969.     }
  2970.  
  2971.     /* Get environment variable.  Return if it does not exist */
  2972.     env_p = getenv(env_var);
  2973.     if (!env_p || !*env_p) {
  2974.         *path = 0;
  2975.         return;
  2976.     }
  2977.  
  2978.     /* Loop thru all paths in the environment variable */
  2979.     env_p = getpath(env_p, path);
  2980.     while (env_p && *path) {
  2981.         p = path + strlen(path);
  2982.         if (((c = *(p - 1)) != '/') && (c != '\\') && (c != ':')) {
  2983.             *p++ = PATHSEP;
  2984.         }
  2985.         strcpy(p, fname);
  2986.         if (access(path, 0) == 0)
  2987.             return;
  2988.         strcpy(p, "codepage/");
  2989.         strcpy(p+9, fname);
  2990.         if (access(path, 0) == 0)
  2991.             return;
  2992.         env_p = getpath(env_p, path);
  2993.     }
  2994.  
  2995.     /* File not found, return an empty string */
  2996.     *path = 0;
  2997. }
  2998.  
  2999.  
  3000. /*
  3001.  *  getpath:  Extract a pathname from a semicolon-delimited list of pathnames
  3002.  */
  3003. char * getpath(register char *src, register char *dst) {
  3004.     const char *keepsrc;
  3005.  
  3006.     keepsrc = src;
  3007.     while (*src && *src != ';') {
  3008.         if (*src != '"') {        /* Process quoted path */
  3009.             *dst++ = *src++;
  3010.         } else {
  3011.             src++;                /* skip over opening quote */
  3012.             while (*src && (*src != '"')) {
  3013.                 *dst++ = *src++;
  3014.             }
  3015.             if (*src) src++;      /* skip over closing quote */
  3016.         }
  3017.     }
  3018.  
  3019.     while ( *src == ';' )  src++;
  3020.     *dst = 0;
  3021.     return((keepsrc != src) ? src : NULL);
  3022. }
  3023.  
  3024. /*
  3025.  * getuniinfo:  Get Unicode Information
  3026.  */
  3027. char * getuniinfo(UniChar uc) {
  3028.     char * unip;
  3029.     UniChar thisuc;
  3030.     int    i;
  3031.  
  3032.     if (uc>=0x4e00 && uc<=0x9fa5)
  3033.         return "4E00;<CJK Ideograph>;Lo;0;L;;;;;N;;;;;";
  3034.     if (uc>=0xac00 && uc<=0xd7a3)
  3035.         return "AC00;<Hangul Syllable>;Lo;0;L;;;;;N;;;;;";
  3036.     if (uc>=0xd800 && uc<=0xdbff)
  3037.         return "DB80;<High Surrogate>;Cs;0;L;;;;;N;;;;;";
  3038.     if (uc>=0xdc00 && uc<=0xdfff)
  3039.         return "DC00;<Low Surrogate>;Cs;0;L;;;;;N;;;;;";
  3040.     if (uc>=0xe000 && uc<=0xf83c)
  3041.         return "E000;<User defined character>;Co;0;L;;;;;N;;;;;";
  3042.  
  3043.     if (!UniTable)
  3044.         readunitab();
  3045.  
  3046.     if (UniTable == (char *)1)
  3047.         return "";
  3048.  
  3049.     unip   = UniTable;
  3050.     while (*unip != 1) {
  3051.         i = gethexval(unip);
  3052.         thisuc = (UniChar)i;
  3053.         if (thisuc > uc && i != NOTHEXVAL)
  3054.             break;
  3055.         if (thisuc == uc)
  3056.             return unip;
  3057.         unip += strlen(unip);
  3058.         while (*unip == 0) {
  3059.             unip++;
  3060.         }
  3061.     }
  3062.     return "";
  3063. }
  3064.  
  3065.  
  3066. /*
  3067.  * readunitab: Read table file
  3068.  */
  3069. int readunitab(void) {
  3070.     FILE * f;
  3071.     ULONG  len;
  3072.     char * unip;
  3073.     int    count;
  3074.  
  3075.     UniTable = (char *)1;
  3076.     f = findopen("unicode.tab", "rb", "PATH", 0);
  3077.     if (!f)
  3078.         return 1;
  3079.  
  3080.     len = filelength(fileno(f));
  3081.     UniTable = malloc(len+2);
  3082.     if (!UniTable) {
  3083.         UniTable = (char *)1;
  3084.         return 1;
  3085.     }
  3086.  
  3087.     count = fread(UniTable, len, 1, f);
  3088.     if (count != 1) {
  3089.         free(UniTable);
  3090.         UniTable = (char *)1;
  3091.         return 1;
  3092.     }
  3093.  
  3094.     UniTable[len]   = 0x00;
  3095.     UniTable[len+1] = 0x01;
  3096.     unip = UniTable;
  3097.     while (*unip != 0x01) {
  3098.         if (*unip == '\r' || *unip == '\n')
  3099.             *unip = 0;
  3100.         unip++;
  3101.     }
  3102.     return 0;
  3103. }
  3104.  
  3105. /*
  3106.  * tokenuni: Tokenize the unicode information
  3107.  */
  3108. void tokenuni(char * str, char * temp, char * token[16]) {
  3109.     char * cp;
  3110.     int  tok;
  3111.  
  3112.     strcpy(temp, str);
  3113.     cp = temp;
  3114.     while (*cp) {
  3115.         if (*cp == ';')
  3116.             *cp = 0;
  3117.         cp++;
  3118.     }
  3119.     memset(cp, 0, 16);
  3120.  
  3121.     cp = temp;
  3122.     for (tok=0; tok<16; tok++) {
  3123.         token[tok]=cp;
  3124.         cp += strlen(cp) + 1;
  3125.     }
  3126. }
  3127.  
  3128.  
  3129. /*
  3130.  * getdesc: Get description
  3131.  */
  3132. char * getdesc(char * name, char * table[]) {
  3133.     char * * tab;
  3134.  
  3135.     tab = table;
  3136.     while (tab[0]) {
  3137.         if (!strcmp(name, tab[0])) {
  3138.             return tab[1];
  3139.         }
  3140.         tab += 2;
  3141.     }
  3142.     return name;
  3143. }
  3144.  
  3145.  
  3146. /*
  3147.  * QueryPrintQueue: Return the default queue name
  3148.  */
  3149. int QueryPrintQueue(char * qname, char * drvname) {
  3150.     ULONG           rc, Returned, Total, Needed;
  3151.     PPRQINFO3       QueueInfo, pqi;
  3152.     LONG            i;
  3153.  
  3154.     /*
  3155.      * Get count of total number of print queues and the size of the
  3156.      * buffer needed (cbNeeded) to hold them.
  3157.      */
  3158.     rc = SplEnumQueue( NULL,          /* pszComputerName - local machine */
  3159.                        3,             /* information level 3 requested   */
  3160.                        NULL,          /* pBuf - NULL for first call      */
  3161.                        0L,            /* cbBuf - 0 to get size needed    */
  3162.                        &Returned,     /* number of queues returned       */
  3163.                        &Total,        /* total number of queues          */
  3164.                        &Needed,       /* number bytes needed             */
  3165.                        NULL );        /* reserved                        */
  3166.  
  3167.     if (!Total)
  3168.         return 1;
  3169.     QueueInfo = malloc(Needed) ;
  3170.  
  3171.     /* Call again to get print queue data. */
  3172.     rc = SplEnumQueue( NULL,             /* pszComputerName - local machine */
  3173.                        3,                /* information level 3 requested   */
  3174.                        QueueInfo,        /* pBuf - gets enumerated queues   */
  3175.                        Needed,           /* cbBuf - size of pBuf            */
  3176.                        &Returned,        /* number of queues returned       */
  3177.                        &Total,           /* total number of queues          */
  3178.                        &Needed,          /* number bytes needed to store    */
  3179.                                          /*   all requested information     */
  3180.                        NULL );           /* reserved                        */
  3181.  
  3182.     strcpy( qname, QueueInfo->pszName );
  3183.     strcpy( drvname, QueueInfo->pszDriverName );
  3184.     for (i = 0; i < Total; ++i) {
  3185.         if ( QueueInfo[i].fsType & PRQ3_TYPE_APPDEFAULT) {
  3186.             strcpy(qname, QueueInfo[i].pszName );
  3187.             strcpy( drvname, QueueInfo[i].pszDriverName );
  3188.             break;
  3189.         }
  3190.     }
  3191.     free (QueueInfo);
  3192.     return 0;
  3193. }
  3194.  
  3195.  
  3196. /*
  3197.  * Types from Unicode tables
  3198.  */
  3199. char * UniTypes[] = {
  3200.     "Lu",  "Uppercase letter",
  3201.     "Ll",  "Lowercase letter",
  3202.     "Lm",  "Modifier letter ",
  3203.     "Lo",  "Other letter",
  3204.     "Lt",  "Titlecase letter ",
  3205.     "Mn",  "Non-spacing mark",
  3206.     "Mc",  "Combining mark",
  3207.     "Nd",  "Decimal number",
  3208.     "No",  "Other number",
  3209.     "Pd",  "Dash punctuation",
  3210.     "Ps",  "Open punctuation",
  3211.     "Pc",  "Under punctuation",
  3212.     "Pe",  "Close punctuation",
  3213.     "Po",  "Other punctuation",
  3214.     "Sm",  "Math symbol",
  3215.     "Sc",  "Currency symbol",
  3216.     "Sk",  "Modifier symbol",
  3217.     "So",  "Other symbol",
  3218.     "Zs",  "Space separator",
  3219.     "Zt",  "Tab separator",
  3220.     "Zl",  "Line separator",
  3221.     "Zp",  "Paragraph separator",
  3222.     "Cc",  "Control or format character",
  3223.     "Co",  "Other character",
  3224.     "Cn",  "Non-character",
  3225.     "Cs",  "Surrogate character",
  3226.     0, 0,
  3227. };
  3228.  
  3229. /*
  3230.  * Bidi types from unicode tables
  3231.  */
  3232. char * BidiTypes[] = {
  3233.     "L",     "Left to right",
  3234.     "R",     "Right to left",
  3235.     "EN",    "European number",
  3236.     "ES",    "European number separator",
  3237.     "ET",    "European number terminator",
  3238.     "AN",    "Arabic number",
  3239.     "CS",    "Common number separator",
  3240.     "B",     "Block separator",
  3241.     "S",     "Segment separator",
  3242.     "WS",    "Whitespace",
  3243.     "MN",    "Mirrored neutral",
  3244.     "ON",    "Other neutral",
  3245.     0, 0,
  3246. };
  3247.