home *** CD-ROM | disk | FTP | other *** search
/ Languages Around the World / LanguageWorld.iso / language / japanese / win_prog / win_jwp / lookup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-31  |  55.9 KB  |  1,724 lines

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3. #include "jwp.h"
  4. #ifdef CTL3D
  5.     #include <ctl3d.h>
  6. #endif CTL3D
  7.  
  8.  
  9. #define KANJIBOXBORDER    AVGWIDTH
  10. #define KANJILISTBORDER   BORDERSPACE
  11. #define SCROLLBLOCKS      5
  12. #define OKURIGANA         0x20
  13.  
  14. #define NRSORT  2
  15. #define MAXLIST 50
  16. #define STROKES 0
  17. #define BUSHU   1
  18.  
  19. typedef struct {
  20.     unsigned char strokes;
  21.     unsigned char bushu;
  22.     unsigned short int nelson;
  23.     unsigned char grade;
  24.     unsigned char on:4;
  25.     unsigned char kun:4;
  26.     unsigned char unknown:4;
  27.     unsigned char meanings:4;
  28.     unsigned char padding;              // To pad it to 32 bits
  29.     unsigned long int offset;
  30. } INFORECORD;
  31.  
  32. typedef struct {
  33.     unsigned char sortkeys[NRSORT];
  34.     KANJI jis;
  35. } IDXRECORD;
  36.  
  37. static OFSTRUCT kinfoidxof;
  38. static BOOL KinfoIdx = FALSE;
  39. static int KinfoMax = -1;
  40. static int SortKey;
  41. static int IdxBase, NrIndex;
  42. static int CurrentKeys[NRSORT];
  43. static int MaxKeys[NRSORT];
  44. static int fd;
  45.  
  46.  
  47. static IDXRECORD KanjiList[MAXLIST];
  48. static int start, stop;
  49. static int NrInList, NrSelected;
  50. static int EdgeGap;
  51.  
  52. static KANJI InfoChar;
  53.  
  54.  
  55. #define NRJISROWS  6
  56.  
  57. static int PageNum;
  58. static int SelRow, SelCol;
  59. static int RowDiv, ColDiv;
  60. static int RowPos, ColPos;
  61.  
  62. BOOL FAR PASCAL KanjiInfoProc (HWND, WORD, WORD, LONG);
  63.  
  64. static KANJI BushuSymbols[] = {
  65.     0x306c, 0x2143, 0x5026, 0x254e, 0x3235,     /* 01 - 05 */
  66.     0x502d, 0x4673, 0x5035, 0x3f4d, 0x5139,     /* 06 - 10 */
  67.     0x467e, 0x482c, 0x5144, 0x514c, 0x5152,     /* 11 - 15 */
  68.     0x515c, 0x5161, 0x4561, 0x4e4f, 0x5231,     /* 16 - 20 */
  69.     0x5238, 0x5239, 0x523e, 0x3d3d, 0x4b4e,     /* 21 - 25 */
  70.     0x5247, 0x524c, 0x5253, 0x4b74, 0x387d,     /* 26 - 30 */
  71.     0x5378, 0x455a, 0x3b4e, 0x5469, 0x546a,     /* 31 - 35 */
  72.     0x4d3c, 0x4267, 0x3d77, 0x3b52, 0x555f,     /* 36 - 40 */
  73.     0x4023, 0x3e2e, 0x5577, 0x5579, 0x4366,     /* 41 - 45 [ 45 qustionable ] */
  74.     0x3b33, 0x406e, 0x3929, 0x384a, 0x3652,     /* 46 - 50 */
  75.     0x3433, 0x5676, 0x5678, 0x572e, 0x5730,     /* 51 - 55 */
  76.     0x5735, 0x355d, 0x4730, 0x5744, 0x5746,     /* 56 - 60 [ 58 questionable ] */
  77.     0x3f34, 0x5879, 0x384d, 0x3c6a, 0x3b59,     /* 61 - 65 */
  78.     0x5a3d, 0x4a38, 0x454d, 0x3654, 0x4a7d,     /* 66 - 70 */
  79.     0x5a5b, 0x467c, 0x5b29, 0x376e, 0x4c5a,     /* 71 - 75 */
  80.     0x3767, 0x3b5f, 0x5d46, 0x5d55, 0x5d59,     /* 76 - 80 */
  81.     0x4866, 0x4c53, 0x3b61, 0x5d63, 0x3f65,     /* 81 - 85 */
  82.     0x3250, 0x445e, 0x4963, 0x602b, 0x602d,     /* 86 - 90 */
  83.     0x4a52, 0x3267, 0x356d, 0x3824, 0x383c,     /* 91 - 95 */
  84.     0x364c, 0x313b, 0x3424, 0x3445, 0x4038,     /* 96 - 100 */
  85.     0x4d51, 0x4544, 0x4925, 0x614b, 0x6222,     /* 101 - 105 [ 104 questionable ] */
  86.     0x4772, 0x4869, 0x3b2e, 0x4c5c, 0x4c37,     /* 106 - 110 */
  87.     0x4c70, 0x4050, 0x3c28, 0x633b, 0x3253,     /* 111 - 115 [ 114 questionable ] */
  88.     0x376a, 0x4e29, 0x435d, 0x4a46, 0x3b65,     /* 116 - 120 */
  89.     0x344c, 0x6626, 0x4d53, 0x3129, 0x4f37,     /* 121 - 125 */
  90.     0x3c29, 0x6650, 0x3c2a, 0x6666, 0x4679,     /* 126 - 130 */
  91.     0x3f43, 0x3c2b, 0x3b6a, 0x3131, 0x4065,     /* 131 - 135 */
  92.     0x4124, 0x3d2e, 0x3a31, 0x3f27, 0x6767,     /* 136 - 140 */
  93.     0x6948, 0x436e, 0x376c, 0x3954, 0x3061,     /* 141 - 145 */
  94.     0x403e, 0x382b, 0x3351, 0x3840, 0x432b,     /* 146 - 150 */
  95.     0x4626, 0x6c35, 0x6c38, 0x332d, 0x4056,     /* 151 - 155 */
  96.     0x4176, 0x422d, 0x3f48, 0x3c56, 0x3f49,     /* 156 - 160 */
  97.     0x4324, 0x6d68, 0x4d38, 0x4653, 0x4850,     /* 161 - 165 [ 162 questionable ] */
  98.     0x4e24, 0x3662, 0x4439, 0x4c67, 0x496c,     /* 166 - 170 */
  99.     0x7030, 0x7032, 0x312b, 0x4044, 0x4873,     /* 171 - 175 */
  100.     0x4c4c, 0x3357, 0x706a, 0x706c, 0x323b,     /* 176 - 180 */
  101.     0x4a47, 0x4977, 0x4874, 0x3f29, 0x3c73,     /* 181 - 185 */
  102.     0x3961, 0x474f, 0x397c, 0x3962, 0x7175,     /* 186 - 190 */
  103.     0x7228, 0x722e, 0x722f, 0x3534, 0x357b,     /* 191 - 195 */
  104.     0x443b, 0x7343, 0x3c2f, 0x734e, 0x4b63,     /* 196 - 200 */
  105.     0x322b, 0x3550, 0x3975, 0x7363, 0x7366,     /* 201 - 205 */
  106.     0x4524, 0x385d, 0x414d, 0x4921, 0x736e,     /* 206 - 210 */
  107.     0x736f, 0x4e36, 0x737d, 0x737e, 0x2121,     /* 211 - 215 */
  108.     0x2121, 0x2121, 0x2121, 0x2121, 0x2121,     /* 216 - 220 */
  109.     0x2121, 0x2121, 0x2121, 0x2121, 0x2121,     /* 221 - 225 */
  110.     0x2121, 0x2121, 0x2121, 0x2121, 0x2121,     /* 226 - 230 */
  111.     0x2121, 0x2121, 0x2121, 0x2121, 0x2121,     /* 231 - 235 */
  112.     0x2121, 0x2121, 0x2121, 0x2121, 0x2121,     /* 236 - 240 */
  113.     0x2121, 0x2121, 0x2121, 0x2121, 0x2121,     /* 241 - 245 */
  114.     0x2121, 0x2121, 0x2121, 0x2121, 0x2121,     /* 246 - 250 */
  115.     0x2121, 0x2121, 0x2121, 0x2121, 0x2121      /* 251 - 255 */
  116. };
  117.  
  118.  
  119.  
  120.  
  121. void SetKanjiInfoChar (KANJI ch)
  122. {
  123.     InfoChar = ch;
  124. }
  125.  
  126.  
  127.  
  128. static int KeysComp (int keys[], IDXRECORD record, int SortKey)
  129. {
  130.     int i;
  131.  
  132.     if (keys[SortKey] != record.sortkeys[SortKey])
  133.         return (keys[SortKey] - record.sortkeys[SortKey]);
  134.  
  135.     for (i = 0; i < NRSORT; i++) {
  136.         if (i == SortKey) continue;
  137.         if (keys[i] != record.sortkeys[i])
  138.             return (keys[i] - record.sortkeys[i]);
  139.     }
  140.  
  141.     return (0);
  142. }
  143.  
  144.  
  145.  
  146. static int BinarySearchIndex (int fd, int which, BOOL lower)
  147. {
  148.     int top, bottom, middle;
  149.     int diff;
  150.     IDXRECORD record;
  151.  
  152.     /* Now binary search */
  153.  
  154.     top = 0;
  155.     bottom = NrIndex - 1;
  156.  
  157.     for (;;) {
  158.         middle = (top + bottom) / 2;
  159.  
  160.         lseek(fd, IdxBase * which + middle * sizeof(IDXRECORD), 0L);
  161.         read(fd, &record, sizeof(IDXRECORD));
  162.  
  163.         diff = KeysComp(CurrentKeys, record, which);
  164.  
  165.         if (diff == 0) {
  166.             /* Move to the beginning */
  167.             while (middle >= 0) {
  168.                 lseek(fd, IdxBase * which + middle * sizeof(IDXRECORD), 0);
  169.                 read(fd, &record, sizeof(IDXRECORD));
  170.                 if (KeysComp(CurrentKeys, record, which) > 0) break;
  171.                 middle--;
  172.             }
  173.  
  174.             return (middle + 1);
  175.         }
  176.  
  177.         if (top >= bottom - 1) return (lower ? bottom : top);
  178.  
  179.         if (diff > 0) top = middle;
  180.         else bottom = middle;
  181.     }
  182. }
  183.  
  184.  
  185.  
  186. static void PerformSearch (HWND hwnd, int fd, BOOL direction, BOOL MainKey)
  187. {
  188.     int i, j;
  189.     IDXRECORD record;
  190.     HCURSOR hCursor;
  191.  
  192.  
  193.     hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  194.     ShowCursor(TRUE);
  195.  
  196.     /* Now binary search the list */
  197.  
  198.     j = BinarySearchIndex(fd, SortKey, TRUE);
  199.     lseek(fd, IdxBase * SortKey + j * sizeof(IDXRECORD), 0);
  200.     read(fd, &record, sizeof(IDXRECORD));
  201.  
  202.     if (MainKey) {
  203.         if (!direction) {
  204.             if (CurrentKeys[SortKey] != record.sortkeys[SortKey]) j--;
  205.         }
  206.     } else {
  207.         if (direction) {
  208.             if (CurrentKeys[SortKey] != record.sortkeys[SortKey]) j--;
  209.         } else {
  210.             if (KeysComp(CurrentKeys, record, SortKey) < 0) {
  211.                 lseek(fd, IdxBase * SortKey + (j-1) * sizeof(IDXRECORD), 0);
  212.                 read(fd, &record, sizeof(IDXRECORD));
  213.                 if (CurrentKeys[SortKey] == record.sortkeys[SortKey]) j--;
  214.             }
  215.         }
  216.     }
  217.  
  218.  
  219.     start = j - NrSelected;
  220.     stop = start + NrInList - 1;
  221.  
  222.     lseek(fd, SortKey * IdxBase, 0);
  223.     if (start > 0) lseek(fd, start * sizeof(IDXRECORD), 1);
  224.  
  225.     for (j = 0; j < NrInList; j++) {
  226.         if (start + j < 0 || start + j >= NrIndex) {
  227.             KanjiList[j].jis = 0;
  228.         } else {
  229.             read(fd, &record, sizeof(IDXRECORD));
  230.             KanjiList[j] = record;
  231.         }
  232.  
  233.         if (j != NrSelected) continue;
  234.  
  235.         for (i = 0; i < NRSORT; i++) {
  236.             if (record.sortkeys[i] != CurrentKeys[i]) {
  237.                 CurrentKeys[i] = record.sortkeys[i];
  238.                 SetScrollPos(GetDlgItem(hwnd, 4221 + i), SB_CTL, CurrentKeys[i], TRUE);
  239.                 SetDlgItemInt(hwnd, 4231 + i, CurrentKeys[i], TRUE);
  240.             }
  241.         }
  242.     }
  243.  
  244.     InvalidateRect(GetDlgItem(hwnd, 4201), NULL, FALSE);
  245.     SendDlgItemMessage(hwnd, 4201, WM_USER, 0, 0L);
  246.  
  247.     ShowCursor(FALSE);
  248.     SetCursor(hCursor);
  249. }
  250.  
  251.  
  252.  
  253. BOOL FAR PASCAL LookupProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  254. {
  255.     int i, j;
  256.     long int offset;
  257.     IDXRECORD record;
  258.  
  259.     switch (message) {
  260.         case WM_INITDIALOG:
  261.             if (!KinfoIdx) {
  262.                 /* Open index file */
  263.  
  264.                 fd = OpenFile(global.kinfoidx, &kinfoidxof, OF_READ);
  265.                 if (fd <= 0) {
  266.                     ErrorMessage(global.hwnd, "Cannot find Kanji info index file!");
  267.                     EndDialog(hwnd, FALSE);
  268.                     return (TRUE);
  269.                 }
  270.                 KinfoIdx = TRUE;
  271.  
  272.                 lseek(fd, 0L, 2);       /* Seek to the end */
  273.                 offset = tell(fd);      /* File size */
  274.  
  275.                 if (offset % sizeof(IDXRECORD) != 0) {
  276.                     ErrorMessage(global.hwnd, "Funny, size of idx = %d", offset);
  277.                 }
  278.  
  279.                 if ((offset / sizeof(IDXRECORD)) % NRSORT != 0) {
  280.                     ErrorMessage(global.hwnd, "Funny, %d not divisible by %d", offset, NRSORT);
  281.                 }
  282.  
  283.                 /* Offset of the last record */
  284.  
  285.                 IdxBase = offset / NRSORT;
  286.                 NrIndex = IdxBase / sizeof(IDXRECORD);
  287.                 offset = IdxBase - sizeof(IDXRECORD);
  288.  
  289.                 /* Get the maximums */
  290.  
  291.                 for (i = 0; i < NRSORT; i++) {
  292.                     lseek(fd, IdxBase * i + offset, 0);
  293.                     read(fd, &record, sizeof(IDXRECORD));
  294.                     MaxKeys[i] = record.sortkeys[i];
  295.                 }
  296.             } else {
  297.                 fd = OpenFile(NULL, &kinfoidxof, OF_READ | OF_REOPEN);
  298.             }
  299.  
  300.             SetDlgItemInt(hwnd, 4231, 1, TRUE);
  301.             SetDlgItemInt(hwnd, 4232, 1, TRUE);
  302.  
  303.             SetWindowPos(GetDlgItem(hwnd, 4241), NULL, 0, 0,
  304.                             SYSFONT->width, SYSFONT->height,
  305.                             SWP_NOMOVE | SWP_NOZORDER);
  306.  
  307.             SetScrollRange(GetDlgItem(hwnd, 4221), SB_CTL, 1, MaxKeys[STROKES], TRUE);
  308.             SetScrollPos(GetDlgItem(hwnd, 4221), SB_CTL, 1, TRUE);
  309.             SetScrollRange(GetDlgItem(hwnd, 4222), SB_CTL, 1, MaxKeys[BUSHU], TRUE);
  310.             SetScrollPos(GetDlgItem(hwnd, 4222), SB_CTL, 1, TRUE);
  311.  
  312.             SetScrollRange(GetDlgItem(hwnd, 4201), SB_HORZ, 0, NrIndex - 1, TRUE);
  313.             SetScrollPos(GetDlgItem(hwnd, 4201), SB_HORZ, 1, TRUE);
  314.  
  315.             SortKey = STROKES;
  316.             for (i = 0; i < NRSORT; i++) CurrentKeys[i] = 1;
  317.  
  318.             SendDlgItemMessage(hwnd, 4211, BM_SETCHECK, 1, 0L);
  319.             SendDlgItemMessage(hwnd, 4212, BM_SETCHECK, 0, 0L);
  320.  
  321.             PerformSearch (hwnd, fd, TRUE, TRUE);
  322.  
  323.             SendMessage(hwnd, WM_USER, 0, 0L);  /* Draw the Bushu icon */
  324.  
  325.             if (global.active == NULL)
  326.                 EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);    /* Insert button */
  327.  
  328.             CenterDialogBox(hwnd);
  329.  
  330.             return (TRUE);
  331.  
  332.         case WM_HSCROLL: {
  333.             HWND child;
  334.             BOOL direction;
  335.  
  336.             child = HIWORD(lParam);
  337.  
  338.             switch (GetWindowWord(child, GWW_ID)) {
  339.                 case 4221:      /* Strokes scrollbar */
  340.                     i = STROKES;
  341.                     break;
  342.  
  343.                 case 4222:      /* Bushu scrollbar */
  344.                     i = BUSHU;
  345.                     break;
  346.  
  347.                 default: return (TRUE);
  348.             }
  349.  
  350.             switch (wParam) {
  351.                 case SB_TOP:
  352.                     CurrentKeys[i] = 1;
  353.                     direction = FALSE;
  354.                     break;
  355.  
  356.                 case SB_BOTTOM:
  357.                     CurrentKeys[i] = MaxKeys[i];
  358.                     direction = TRUE;
  359.                     break;
  360.  
  361.                 case SB_LINEUP:
  362.                     if (CurrentKeys[i] <= 1) return (TRUE);
  363.                     CurrentKeys[i]--;
  364.                     direction = FALSE;
  365.                     break;
  366.  
  367.                 case SB_PAGEUP:
  368.                     if (CurrentKeys[i] <= 1) return (TRUE);
  369.                     CurrentKeys[i] -= (MaxKeys[i] / SCROLLBLOCKS);
  370.                     if (CurrentKeys[i] < 1) CurrentKeys[i] = 1;
  371.                     direction = FALSE;
  372.                     break;
  373.  
  374.                 case SB_LINEDOWN:
  375.                     if (CurrentKeys[i] >= MaxKeys[i]) return (TRUE);
  376.                     CurrentKeys[i]++;
  377.                     direction = TRUE;
  378.                     break;
  379.  
  380.                 case SB_PAGEDOWN:
  381.                     if (CurrentKeys[i] >= MaxKeys[i]) return (TRUE);
  382.                     CurrentKeys[i] += (MaxKeys[i] / SCROLLBLOCKS);
  383.                     if (CurrentKeys[i] > MaxKeys[i]) CurrentKeys[i] = MaxKeys[i];
  384.                     direction = TRUE;
  385.                     break;
  386.  
  387.                 case SB_THUMBPOSITION:
  388.                 case SB_THUMBTRACK:
  389.                     CurrentKeys[i] = LOWORD(lParam);
  390.                     direction = TRUE;
  391.                     break;
  392.  
  393.                 default: return (TRUE);
  394.             }
  395.  
  396.             SetScrollPos(child, SB_CTL, CurrentKeys[i], TRUE);
  397.             SetDlgItemInt(hwnd, 4231 + i, CurrentKeys[i], TRUE);
  398.  
  399.             if (wParam == SB_THUMBTRACK) {
  400.                 if (4231 + i == 4232) {     /* Bushu */
  401.                     SendMessage(hwnd, WM_USER, 0, 0L);  /* Draw the Bushu icon */
  402.                 }
  403.  
  404.                 return (TRUE);
  405.             }
  406.  
  407.             /* Set everything else to 1? */
  408.  
  409.             if (i == SortKey) {
  410.                 for (j = 0; j < NRSORT; j++) {
  411.                     if (j == SortKey) continue;
  412.                     CurrentKeys[j] = 1;
  413.                     SetScrollPos(GetDlgItem(hwnd, 4221 + j), SB_CTL, 1, TRUE);
  414.                     SetDlgItemInt(hwnd, 4231 + j, 1, TRUE);
  415.  
  416.                     if (4231 + j == 4232) {     /* Bushu */
  417.                         SendMessage(hwnd, WM_USER, 0, 0L);  /* Draw the Bushu icon */
  418.                     }
  419.                 }
  420.             }
  421.  
  422.             PerformSearch (hwnd, fd, direction, i == SortKey);
  423.  
  424.             SendMessage(hwnd, WM_USER, 0, 0L);  /* Draw the Bushu icon */
  425.  
  426.             return (TRUE);
  427.         }
  428.  
  429.         case WM_PAINT:
  430.             SendMessage(hwnd, WM_USER, 0, 0L);  /* Draw the Bushu icon */
  431.             break;
  432.  
  433.         case WM_USER: {
  434.             int r, Bushu;
  435.             HDC hdc;
  436.             BYTE far *cbufp;
  437.             extern BOOL Dialogs3D;
  438.  
  439.             Bushu = CurrentKeys[1];
  440.  
  441.             if (Bushu <= 0 || Bushu > 214) break;
  442.  
  443.             hdc = GetDC(GetDlgItem(hwnd, 4241));
  444.             SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  445.             SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  446.  
  447. #ifdef CTL3D
  448.             if (Dialogs3D) {
  449.                 RECT rect;
  450.                 HBRUSH hbrush;
  451.  
  452.                 hbrush = Ctl3dCtlColorEx(WM_CTLCOLOR, hdc, MAKELONG(hwnd, CTLCOLOR_DLG));
  453.                 GetClientRect(GetDlgItem(hwnd, 4241), &rect);
  454.                 FillRect(hdc, &rect, hbrush);
  455.             } else
  456. #endif CTL3D
  457.             {
  458.                 HBRUSH hbrush;
  459.                 RECT rect;
  460.  
  461.                 hbrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  462.                 GetClientRect(GetDlgItem(hwnd, 4241), &rect);
  463.                 FillRect(hdc, &rect, hbrush);
  464.                 DeleteObject(hbrush);
  465.             }
  466.  
  467.             r = Jis2Index(BushuSymbols[Bushu - 1], SYSFONT->holes);
  468.             if (r >= 0) {
  469.                 r = GetKanjiBitmap(SYSFONT, r, &cbufp);
  470.                 DisplayKanjiBitmap(hdc, 0, SYSFONT->height,
  471.                                     SYSFONT->width, SYSFONT->height,
  472.                                     r, SRCAND, cbufp);
  473.             }
  474.  
  475.             ReleaseDC(GetDlgItem(hwnd, 4241), hdc);
  476.             return (TRUE);
  477.         }
  478.  
  479.         case WM_COMMAND:
  480.             switch (wParam) {
  481.                 case 4211:      /* Strokes first */
  482.                     SendDlgItemMessage(hwnd, 4211, BM_SETCHECK, 1, 0L);
  483.                     SendDlgItemMessage(hwnd, 4212, BM_SETCHECK, 0, 0L);
  484.                     SortKey = STROKES;
  485.                     PerformSearch (hwnd, fd, TRUE, TRUE);
  486.                     return (TRUE);
  487.  
  488.                 case 4212:      /* Bushu first */
  489.                     SendDlgItemMessage(hwnd, 4211, BM_SETCHECK, 0, 0L);
  490.                     SendDlgItemMessage(hwnd, 4212, BM_SETCHECK, 1, 0L);
  491.                     SortKey = BUSHU;
  492.                     PerformSearch (hwnd, fd, TRUE, TRUE);
  493.                     return (TRUE);
  494.  
  495.                 case 4213:      /* Info */
  496.                     SetKanjiInfoChar(KanjiList[NrSelected].jis);
  497.  
  498.                     DialogBox (hInstance, "KanjiInfo", hwnd, KanjiInfoProc);
  499.                     return (TRUE);
  500.  
  501.                 case IDOK: {        /* Insert button */
  502.                     KANJI buf[2];
  503.  
  504.                     if (curfile != NULL) {
  505.                         buf[0] = KanjiList[NrSelected].jis;
  506.                         buf[1] = 0;
  507.  
  508.                         TurnOffSelection(curfile);
  509.                         UndoAddTyping(curfile, curfile->current, 1, FALSE);
  510.                         InsertString(curfile, curfile->current, buf,
  511.                                         OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND);
  512.                     }
  513.                 }
  514.                 /* ... drops into the next case ... */
  515.  
  516.                 case IDCANCEL:
  517.                     EndDialog(hwnd, FALSE);
  518.                     close(fd);
  519.                     return (TRUE);
  520.  
  521.                 default: break;
  522.             }
  523.             break;
  524.     }
  525.  
  526.     return (FALSE);
  527. }
  528.  
  529.  
  530.  
  531. LONG FAR PASCAL LookupListProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  532. {
  533.     int i, j, r;
  534.     RECT rect;
  535.     HDC hdc;
  536.     HWND parent;
  537.     HBRUSH hbrush;
  538.     HPEN hpen;
  539.     PAINTSTRUCT ps;
  540.     IDXRECORD record;
  541.     BYTE far *cbufp;
  542.  
  543.     switch (message) {
  544.  
  545.         case WM_CREATE:
  546.             GetClientRect(hwnd, &rect);
  547.             i = GetSystemMetrics(SM_CYHSCROLL) + SYSFONT->height + 1
  548.                 + 2 * KANJILISTBORDER;
  549.  
  550.             SetWindowPos(hwnd, NULL, 0, 0, rect.right, i, SWP_NOMOVE | SWP_NOZORDER);
  551.  
  552.             NrInList = (rect.right - 2 * KANJILISTBORDER) / SYSFONT->width;
  553.             NrInList /= 2;
  554.  
  555.             if (NrInList % 2 != 0) NrSelected = NrInList / 2;
  556.             else NrSelected = (NrInList / 2) - 1;
  557.  
  558.             if (NrInList <= 1) NrInList = NrSelected = 1;
  559.             EdgeGap = (rect.right - (NrInList * 2 - 1) * SYSFONT->width) / 2;
  560.             if (EdgeGap < 0) EdgeGap = 1;
  561.             return (0);
  562.  
  563.         case WM_GETDLGCODE:
  564.             return (DLGC_WANTARROWS);
  565.  
  566.         case WM_LBUTTONDOWN: {
  567.             int x;
  568.  
  569.             x = LOWORD(lParam);
  570.             GetClientRect(hwnd, &rect);
  571.  
  572.             /* Find out which character it clicks on */
  573.  
  574.             i = (x + (SYSFONT->width / 2) - EdgeGap) / (2 * SYSFONT->width);
  575.             if (KanjiList[i].jis == 0 || i < 0 || i > NrInList) {
  576.                 MessageBeep(0);
  577.                 return (0);
  578.             }
  579.  
  580.             /* Change the high-light */
  581.  
  582.             hdc = GetDC(hwnd);
  583.             SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  584.             SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  585.             PatBlt(hdc, (NrSelected * 2 * SYSFONT->width) + EdgeGap - (SYSFONT->width / 2),
  586.                     2, 2 * SYSFONT->width, rect.bottom - 4, DSTINVERT);
  587.             PatBlt(hdc, (i * 2 * SYSFONT->width) + EdgeGap - (SYSFONT->width / 2),
  588.                     2, 2 * SYSFONT->width, rect.bottom - 4, DSTINVERT);
  589.             ReleaseDC(hwnd, hdc);
  590.  
  591.             NrSelected = i;
  592.  
  593.  
  594.             /* Change the scroll bars */
  595.  
  596.             for (j = 0; j < NRSORT; j++) {
  597.                 CurrentKeys[j] = KanjiList[NrSelected].sortkeys[j];
  598.                 SetScrollPos(GetDlgItem(GetParent(hwnd), 4221 + j), SB_CTL, CurrentKeys[j], TRUE);
  599.                 SetDlgItemInt(GetParent(hwnd), 4231 + j, CurrentKeys[j], TRUE);
  600.  
  601.                 if (4231 + j == 4232) {     /* Bushu */
  602.                     SendMessage(GetParent(hwnd), WM_USER, 0, 0L);  /* Draw the Bushu icon */
  603.                 }
  604.             }
  605.             return (0);
  606.         }
  607.  
  608.         case WM_LBUTTONDBLCLK:
  609.             SendMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0L);
  610.             return (0);
  611.  
  612.         case WM_PAINT:
  613.             GetClientRect(hwnd, &rect);
  614.             hdc = BeginPaint(hwnd, &ps);
  615.  
  616.             SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  617.             SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  618.             hbrush = SelectObject(hdc, GetStockObject(NULL_BRUSH));
  619.             hpen = SelectObject(hdc, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME)));
  620.  
  621.             Rectangle(hdc, 0, 0, rect.right, rect.bottom);
  622.  
  623.             DeleteObject(SelectObject(hdc, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW))));
  624.  
  625.             Rectangle(hdc, 1, 1, rect.right - 1, rect.bottom - 1);
  626.  
  627.             SelectObject(hdc, CreateSolidBrush(GetSysColor(COLOR_WINDOW)));
  628.  
  629.             //EnableFontCache(FALSE);
  630.  
  631.             for (i = 0, j = EdgeGap; i < NrInList; i++, j += 2 * SYSFONT->width) {
  632.                 if (KanjiList[i].jis == 0) {
  633.                     PatBlt(hdc, j, KANJILISTBORDER, SYSFONT->width,
  634.                             SYSFONT->height, PATCOPY);
  635.                     continue;
  636.                 }
  637.  
  638.                 r = Jis2Index(KanjiList[i].jis, SYSFONT->holes);
  639.                 if (r < 0) r = Jis2Index(BADKANJI, SYSFONT->holes);
  640.                 r = GetKanjiBitmap(SYSFONT, r, &cbufp);
  641.  
  642.                 if (i == NrSelected) {
  643.                     HBRUSH hbrush1;
  644.  
  645.                     hbrush1 = SelectObject(hdc, CreateSolidBrush(~GetSysColor(COLOR_WINDOW)));
  646.                     PatBlt(hdc, j - (SYSFONT->width / 2), 2,
  647.                             2 * SYSFONT->width, rect.bottom - 4, PATCOPY);
  648.                     DeleteObject(SelectObject(hdc, hbrush1));
  649.  
  650.                     DisplayKanjiBitmap(hdc, j, KANJILISTBORDER + SYSFONT->height,
  651.                                         SYSFONT->width, SYSFONT->height,
  652.                                         r, NOTSRCCOPY, cbufp);
  653.                 } else {
  654.                     DisplayKanjiBitmap(hdc, j, KANJILISTBORDER + SYSFONT->height,
  655.                                         SYSFONT->width, SYSFONT->height,
  656.                                         r, SRCCOPY, cbufp);
  657.                 }
  658.             }
  659.  
  660.             DeleteObject(SelectObject(hdc, hpen));
  661.             DeleteObject(SelectObject(hdc, hbrush));
  662.  
  663.             //EnableFontCache(TRUE);
  664.  
  665.             EndPaint(hwnd, &ps);
  666.             return (0);
  667.  
  668.         case WM_USER:
  669.             SetScrollPos(hwnd, SB_HORZ, start + NrSelected, TRUE);
  670.             return (0);
  671.  
  672.         case WM_KEYDOWN:
  673.             switch (wParam) {
  674.                 case VK_LEFT:   SendMessage(hwnd, WM_HSCROLL, SB_LINEUP, 0L); break;
  675.                 case VK_RIGHT:  SendMessage(hwnd, WM_HSCROLL, SB_LINEDOWN, 0L); break;
  676.                 case VK_PRIOR:  SendMessage(hwnd, WM_HSCROLL, SB_PAGEUP, 0L); break;
  677.                 case VK_NEXT:   SendMessage(hwnd, WM_HSCROLL, SB_PAGEDOWN, 0L); break;
  678.                 case VK_UP:     SendMessage(hwnd, WM_HSCROLL, SB_LINEUP, 0L); break;
  679.                 case VK_DOWN:   SendMessage(hwnd, WM_HSCROLL, SB_LINEDOWN, 0L); break;
  680.             }
  681.             return (0);
  682.  
  683.         case WM_HSCROLL:
  684.             switch (wParam) {
  685.                 case SB_LINEUP:
  686.                     if (start + NrSelected <= 0) return (TRUE);
  687.                     start--;
  688.                     stop = start + NrInList - 1;
  689.                     for (i = NrInList - 1; i >= 0; i--) KanjiList[i] = KanjiList[i-1];
  690.                     if (start < 0) {
  691.                         KanjiList[0].jis = 0;
  692.                     } else {
  693.                         lseek(fd, SortKey * IdxBase + start * sizeof(IDXRECORD), 0);
  694.                         read(fd, &record, sizeof(IDXRECORD));
  695.                         KanjiList[0] = record;
  696.                     }
  697.                     InvalidateRect(hwnd, NULL, FALSE);
  698.                     break;
  699.  
  700.                 case SB_PAGEUP:
  701.                     if (start + NrSelected <= 0) return (TRUE);
  702.                     start -= NrInList;
  703.                     stop = start + NrInList - 1;
  704.                     if (start + NrSelected <= 0) start = -NrSelected + 1;
  705.                     if (start >= 0) {
  706.                         lseek(fd, SortKey * IdxBase + start * sizeof(IDXRECORD), 0);
  707.                     } else {
  708.                         lseek(fd, SortKey * IdxBase, 0);
  709.                     }
  710.                     for (i = 0; i < NrInList; i++) {
  711.                         if (start + i < 0 || start + i >= NrIndex) {
  712.                             KanjiList[i].jis = 0;
  713.                         } else {
  714.                             read(fd, &record, sizeof(IDXRECORD));
  715.                             KanjiList[i] = record;
  716.                         }
  717.                     }
  718.                     InvalidateRect(hwnd, NULL, FALSE);
  719.                     break;
  720.  
  721.                 case SB_LINEDOWN:
  722.                     if (start + NrSelected >= NrIndex - 1) return (TRUE);
  723.                     start++;
  724.                     stop = start + NrInList - 1;
  725.                     for (i = 0; i < NrInList - 1; i++) KanjiList[i] = KanjiList[i+1];
  726.                     if (start + NrInList - 1 >= NrIndex) {
  727.                         KanjiList[NrInList - 1].jis = 0;
  728.                     } else {
  729.                         lseek(fd, SortKey * IdxBase + stop * sizeof(IDXRECORD), 0);
  730.                         read(fd, &record, sizeof(IDXRECORD));
  731.                         KanjiList[NrInList - 1] = record;
  732.                     }
  733.                     InvalidateRect(hwnd, NULL, FALSE);
  734.                     break;
  735.  
  736.                 case SB_PAGEDOWN:
  737.                     if (start + NrSelected >= NrIndex - 1) return (TRUE);
  738.                     start += NrInList;
  739.                     stop = start + NrInList - 1;
  740.                     if (start + NrSelected >= NrIndex - 1) start = NrIndex - NrSelected;
  741.                     for (i = 0; i < NrInList; i++) {
  742.                         if (start + i < 0 || start + i >= NrIndex) {
  743.                             KanjiList[i].jis = 0;
  744.                         } else {
  745.                             read(fd, &record, sizeof(IDXRECORD));
  746.                             KanjiList[i] = record;
  747.                         }
  748.                     }
  749.                     InvalidateRect(hwnd, NULL, FALSE);
  750.                     break;
  751.  
  752.                 default: return (TRUE);
  753.             }
  754.  
  755.             parent = GetParent(hwnd);
  756.  
  757.             for (i = 0; i < NRSORT; i++) {
  758.                 if (KanjiList[NrSelected].sortkeys[i] != CurrentKeys[i]) {
  759.                     CurrentKeys[i] = KanjiList[NrSelected].sortkeys[i];
  760.                     SetScrollPos(GetDlgItem(parent, 4221 + i), SB_CTL, CurrentKeys[i], TRUE);
  761.                     SetDlgItemInt(parent, 4231 + i, CurrentKeys[i], TRUE);
  762.  
  763.                     if (4231 + i == 4232) {     /* Bushu */
  764.                         SendMessage(parent, WM_USER, 0, 0L);  /* Draw the Bushu icon */
  765.                     }
  766.                 }
  767.             }
  768.             return (TRUE);
  769.     }
  770.  
  771.     return (DefWindowProc(hwnd, message, wParam, lParam));
  772. }
  773.  
  774.  
  775.  
  776. static KANJI CheckHexJISCode (HWND hwnd, char *s)
  777. {
  778.     KANJI ch;
  779.     int i;
  780.  
  781.     if (strlen(s) != 4) goto BadCode;
  782.  
  783.     for (i = 0; s[i]; i++) {
  784.         if (strchr("0123456789ABCDEF", s[i]) == NULL)
  785.             goto BadHexNumber;
  786.     }
  787.  
  788.     ch = 0;
  789.  
  790.     for (i = 0; i < 4 && s[i]; i++) {
  791.         ch <<= 4;
  792.         if ('0' <= s[i] && s[i] <= '9') ch |= (s[i] - '0');
  793.         else ch |= (s[i] - 'A' + 10);
  794.     }
  795.     ch &= 0x7f7f;
  796.  
  797.     if (Jis2Index(ch, FALSE) < 0) goto BadCode;
  798.  
  799.     return (ch);
  800.  
  801.  
  802. BadCode:
  803.  
  804.     ErrorMessage(hwnd, "'%s' is not a valid JIS code.  Please try again.", s);
  805.     return (0);
  806.  
  807. BadHexNumber:
  808.  
  809.     ErrorMessage(hwnd, "'%s' is not a valid HEX number.\n\n"
  810.                           "Remember, you must type the\n"
  811.                           "JIS code in HEX, e.g. 3A4B", s);
  812.  
  813.     return (0);
  814. }
  815.  
  816.  
  817.  
  818. BOOL FAR PASCAL JISInputProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  819. {
  820.     switch (message) {
  821.         case WM_INITDIALOG:
  822.             SendDlgItemMessage(hwnd, 4201, EM_LIMITTEXT, 4, 0L);
  823.             if (global.active == NULL)
  824.                 EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);    /* Insert button */
  825.  
  826.             CenterDialogBox(hwnd);
  827.             return (TRUE);
  828.  
  829.         case WM_COMMAND:
  830.             switch (wParam) {
  831.                 case 4211: {    /* Info button */
  832.                     KANJI ch;
  833.                     char textbuf[5];
  834.  
  835.                     GetDlgItemText(hwnd, 4201, textbuf, 5);
  836.                     ch = CheckHexJISCode(hwnd, textbuf);
  837.  
  838.                     if (!ch) {
  839.                         SetDlgItemText(hwnd, 4201, "");
  840.                         SetFocus(GetDlgItem(hwnd, 4201));
  841.                         return (TRUE);
  842.                     }
  843.  
  844.                     SetKanjiInfoChar(ch);
  845.  
  846.                     DialogBox (hInstance, "KanjiInfo", hwnd, KanjiInfoProc);
  847.                     return (TRUE);
  848.                 }
  849.  
  850.                 case IDOK: {        /* Insert that character? */
  851.                     char textbuf[5];
  852.                     KANJI buf[2];
  853.  
  854.                     if (HIWORD(lParam) != BN_CLICKED) return (TRUE);
  855.  
  856.                     /* Value OK? */
  857.  
  858.                     GetDlgItemText(hwnd, 4201, textbuf, 5);
  859.  
  860.                     buf[0] = CheckHexJISCode(hwnd, textbuf);
  861.                     if (!buf[0]) {
  862.                         SetDlgItemText(hwnd, 4201, "");
  863.                         SetFocus(GetDlgItem(hwnd, 4201));
  864.                         return (TRUE);
  865.                     }
  866.  
  867.                     buf[1] = 0;
  868.  
  869.                     if (curfile != NULL) {
  870.                         TurnOffSelection(curfile);
  871.                         UndoAddTyping(curfile, curfile->current, 1, FALSE);
  872.                         InsertString(curfile, curfile->current, buf,
  873.                                         OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND);
  874.                         SendMessage(hwnd, WM_COMMAND, IDCANCEL, 0L);
  875.                     }
  876.  
  877.                     EndDialog(hwnd, FALSE);
  878.                     return (TRUE);
  879.                 }
  880.  
  881.                 case IDCANCEL:
  882.                     EndDialog(hwnd, FALSE);
  883.                     return (TRUE);
  884.             }
  885.             break;
  886.     }
  887.     return (FALSE);
  888. }
  889.  
  890.  
  891.  
  892. BOOL FAR PASCAL KanjiInfoProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  893. {
  894.     static int Kinfo = 0;       /* 0 = not open, 1 = open, 2 = can't find */
  895.     static int Bushu = 0;
  896.     static OFSTRUCT kinfoof;
  897.     static KANJI far *OnKunPtr;
  898.  
  899.  
  900.     switch (message) {
  901.  
  902.         case WM_INITDIALOG: {
  903.             INFORECORD record;
  904.             KANJI ch;
  905.             FILE *fp;
  906.             char buffer[MAXLINELEN];
  907.             int i, j;
  908.             int seq, fd, onkunx;
  909.             BOOL okurigana;
  910.  
  911.             CenterDialogBox(hwnd);
  912.  
  913.             Bushu = 0;
  914.  
  915.             ch = InfoChar & 0x7f7f;
  916.  
  917.             SendDlgItemMessage(hwnd, 4201, WM_USER, ch, 0L);
  918.  
  919.             if (ch > 0) {
  920.                 sprintf(buffer, "%X (%X) [ %c%c ]", (int) ch, ((int) ch) | 0x8080,
  921.                                     HIBYTE(ch) & 0x007f, LOBYTE(ch) & 0x007f);
  922.             } else {
  923.                 strcpy(buffer, "Unknown");
  924.             }
  925.             SetDlgItemText(hwnd, 4213, buffer);
  926.  
  927.             if (!ISKANJI(ch)) return (TRUE);
  928.  
  929.             /* Now figure out the sequence number of the kanji */
  930.  
  931.             ch -= 0x3021;
  932.             seq = HIBYTE(ch) * 94 + LOBYTE(ch);
  933.  
  934.             switch (Kinfo) {
  935.                 case 0:
  936.                     fd = OpenFile(global.kinfo, &kinfoof, OF_READ);
  937.                     if (fd <= 0) {
  938.                         ErrorMessage(hwnd, "Cannot open Kanji Info file!");
  939.                         Kinfo = 2;
  940.                         return (TRUE);
  941.                     }
  942.                     Kinfo = 1;
  943.                     break;
  944.  
  945.                 case 1:
  946.                     fd = OpenFile(NULL, &kinfoof, OF_READ | OF_REOPEN);
  947.                     break;
  948.  
  949.                 case 2:
  950.                 default:
  951.                     return (TRUE);
  952.             }
  953.  
  954.             if (KinfoMax < 0) {
  955.                 lseek(fd, 0L, 0);
  956.                 read(fd, &record, sizeof(INFORECORD));
  957.  
  958.                 KinfoMax = record.offset / sizeof(INFORECORD);
  959.                 if (KinfoMax < 0) ErrorMessage(hwnd, "Corrupted kanji info file!");
  960.             }
  961.  
  962.             if (seq > KinfoMax) {
  963.                 close(fd);
  964.                 return (TRUE);
  965.             }
  966.  
  967.             lseek(fd, (long int) seq * sizeof(INFORECORD), 0);
  968.             read(fd, &record, sizeof(INFORECORD));
  969.  
  970.             SetDlgItemInt(hwnd, 4211, record.strokes, TRUE);
  971.             SetDlgItemInt(hwnd, 4212, record.bushu, TRUE);
  972.             if (record.grade <= 0) {
  973.                 SetDlgItemText(hwnd, 4214, "None");
  974.             } else {
  975.                 SetDlgItemInt(hwnd, 4214, record.grade, TRUE);
  976.             }
  977.             if (record.nelson <= 0) {
  978.                 SetDlgItemText(hwnd, 4215, "None");
  979.             } else {
  980.                 SetDlgItemInt(hwnd, 4215, record.nelson, TRUE);
  981.             }
  982.  
  983.             Bushu = record.bushu;
  984.  
  985.             SetWindowPos(GetDlgItem(hwnd, 4231), NULL, 0, 0,
  986.                             SYSFONT->width, SYSFONT->height,
  987.                             SWP_NOMOVE | SWP_NOZORDER);
  988.  
  989.             /* Now read the On/Kun readings and meanings */
  990.  
  991.             OnKunPtr = MemAlloc(MAXLINELEN * sizeof(KANJI));
  992.             if (OnKunPtr == NULL) return (TRUE);
  993.  
  994.             onkunx = 0;
  995.  
  996.             fp = fdopen(fd, "rb");
  997.             if (fp == NULL) {
  998.                 FreeMem((void *) OnKunPtr);
  999.                 close(fd);
  1000.                 goto NoInfo;
  1001.             }
  1002.  
  1003.             fseek(fp, record.offset, 0);
  1004.  
  1005.             SendDlgItemMessage(hwnd, 4221, WM_SETREDRAW, FALSE, 0L);
  1006.             SendDlgItemMessage(hwnd, 4222, WM_SETREDRAW, FALSE, 0L);
  1007.             SendDlgItemMessage(hwnd, 4223, WM_SETREDRAW, FALSE, 0L);
  1008.  
  1009.             for (i = 0; i < record.on; i++) {
  1010.                 fgets(buffer, MAXLINELEN, fp);
  1011.                 for (j = strlen(buffer); j >= 0 && buffer[j] <= ' '; j--);
  1012.                 buffer[j+1] = '\0';
  1013.  
  1014.                 for (j = 0; buffer[j]; j++) OnKunPtr[onkunx+j] = 0x2400 | (buffer[j] & 0x007f);
  1015.                 OnKunPtr[onkunx+j] = 0;
  1016.                 SendDlgItemMessage(hwnd, 4221, LB_ADDSTRING, 0, (LONG) (OnKunPtr + onkunx));
  1017.                 onkunx += (j + 1);
  1018.             }
  1019.  
  1020.             for (i = 0; i < record.kun; i++) {
  1021.                 fgets(buffer, MAXLINELEN, fp);
  1022.                 for (j = strlen(buffer); j >= 0 && buffer[j] <= ' '; j--);
  1023.                 buffer[j+1] = '\0';
  1024.  
  1025.                 okurigana = FALSE;
  1026.  
  1027.                 for (j = 0; buffer[j]; j++) {
  1028.                     if (buffer[j] == OKURIGANA) {
  1029.                         OnKunPtr[onkunx+j] = 0x214a;    /* ( */
  1030.                         okurigana = TRUE;
  1031.                     } else {
  1032.                         OnKunPtr[onkunx+j] = 0x2400 | (buffer[j] & 0x007f);
  1033.                     }
  1034.                 }
  1035.                 if (okurigana) {
  1036.                     OnKunPtr[onkunx+j] = 0x214b;    /* ) */
  1037.                     j++;
  1038.                 }
  1039.                 OnKunPtr[onkunx+j] = 0;
  1040.                 SendDlgItemMessage(hwnd, 4222, LB_ADDSTRING, 0, (LONG) (OnKunPtr + onkunx));
  1041.                 onkunx += (j + 1);
  1042.             }
  1043.  
  1044.             for (i = 0; i < record.meanings; i++) {
  1045.                 fgets(buffer, MAXLINELEN, fp);
  1046.                 for (j = strlen(buffer); j >= 0 && buffer[j] <= ' '; j--);
  1047.                 buffer[j+1] = '\0';
  1048.  
  1049.                 SendDlgItemMessage(hwnd, 4223, LB_ADDSTRING, 0, (LONG) buffer);
  1050.             }
  1051.  
  1052.             fclose(fp);
  1053.  
  1054.             SendDlgItemMessage(hwnd, 4221, WM_SETREDRAW, TRUE, 0L);
  1055.             SendDlgItemMessage(hwnd, 4222, WM_SETREDRAW, TRUE, 0L);
  1056.             SendDlgItemMessage(hwnd, 4223, WM_SETREDRAW, TRUE, 0L);
  1057.             InvalidateRect(GetDlgItem(hwnd, 4221), NULL, TRUE);
  1058.             InvalidateRect(GetDlgItem(hwnd, 4222), NULL, TRUE);
  1059.             InvalidateRect(GetDlgItem(hwnd, 4223), NULL, TRUE);
  1060.  
  1061.             return (TRUE);
  1062.  
  1063. NoInfo:     ErrorMessage(hwnd, "You must select (highlight) a KANJI");
  1064.             EndDialog(hwnd, FALSE);
  1065.             return (TRUE);
  1066.         }
  1067.  
  1068.         case WM_PAINT: {
  1069.             int r;
  1070.             HDC hdc;
  1071.             BYTE far *cbufp;
  1072.  
  1073.             if (Bushu <= 0 || Bushu > 214) break;
  1074.  
  1075.             hdc = GetDC(GetDlgItem(hwnd, 4231));
  1076.             SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  1077.             SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  1078.  
  1079. #ifdef CTL3D
  1080.             if (Dialogs3D) {
  1081.                 RECT rect;
  1082.                 HBRUSH hbrush;
  1083.  
  1084.                 hbrush = Ctl3dCtlColorEx(WM_CTLCOLOR, hdc, MAKELONG(hwnd, CTLCOLOR_DLG));
  1085.                 GetClientRect(GetDlgItem(hwnd, 4241), &rect);
  1086.                 FillRect(hdc, &rect, hbrush);
  1087.             } else
  1088. #endif CTL3D
  1089.             {
  1090.                 HBRUSH hbrush;
  1091.                 RECT rect;
  1092.  
  1093.                 hbrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  1094.                 GetClientRect(hwnd, &rect);
  1095.                 FillRect(hdc, &rect, hbrush);
  1096.                 DeleteObject(hbrush);
  1097.             }
  1098.  
  1099.             r = Jis2Index(BushuSymbols[Bushu - 1], SYSFONT->holes);
  1100.             if (r >= 0) {
  1101.                 r = GetKanjiBitmap(SYSFONT, r, &cbufp);
  1102.                 DisplayKanjiBitmap(hdc, 0, SYSFONT->height,
  1103.                                     SYSFONT->width, SYSFONT->height,
  1104.                                     r, SRCAND, cbufp);
  1105.             }
  1106.             ReleaseDC(GetDlgItem(hwnd, 4231), hdc);
  1107.             break;
  1108.         }
  1109.  
  1110.         case WM_COMMAND:
  1111.             switch (wParam) {
  1112.                 case IDOK:
  1113.                 case IDCANCEL:
  1114.                     EndDialog(hwnd, FALSE);
  1115.                     return (TRUE);
  1116.  
  1117.                 default: break;
  1118.             }
  1119.             break;
  1120.  
  1121.         case WM_DESTROY:
  1122.             FreeMem((void *) OnKunPtr);
  1123.             return (TRUE);
  1124.         
  1125.         case WM_COMPAREITEM:
  1126.         case WM_DELETEITEM:
  1127.         case WM_DRAWITEM:
  1128.         case WM_MEASUREITEM:
  1129.             return (JlistProc(hwnd, message, wParam, lParam, TRUE, (LONG) NULL));
  1130.     }
  1131.  
  1132.     return (FALSE);
  1133. }
  1134.  
  1135.  
  1136.  
  1137. LONG FAR PASCAL BigKanjiProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  1138. {
  1139.     static OFSTRUCT of;
  1140.     static FONTHEADER fh;
  1141.     static int LargeFont = 0;   /* 0 = Not yet open, 1 = opened, 2 = not available */
  1142.  
  1143.     switch (message) {
  1144.  
  1145.         case WM_CREATE:
  1146.             SetWindowWord(hwnd, 0, 0);
  1147.             return (0);
  1148.  
  1149.         case WM_PAINT: {
  1150.             int i, j, fd;
  1151.             int width, height;
  1152.             LONG offset;
  1153.             LONG area, LargestArea;
  1154.             KANJI index;
  1155.             BYTE far *cbufp, buffer[BUFSIZE], tempbuf[BUFSIZE];
  1156.             HDC hdc, hdcmem;
  1157.             HANDLE hbitmap;
  1158.             HBRUSH hbrush;
  1159.             HPEN hpen;
  1160.             RECT rect;
  1161.             PAINTSTRUCT ps;
  1162.  
  1163.  
  1164.             hdc = BeginPaint(hwnd, &ps);
  1165.  
  1166.             SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  1167.             SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  1168.             hbrush = SelectObject(hdc, CreateSolidBrush(GetSysColor(COLOR_WINDOW)));
  1169.             hpen = SelectObject(hdc, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME)));
  1170.  
  1171.             GetClientRect(hwnd, &rect);
  1172.             Rectangle(hdc, 0, 0, rect.right, rect.bottom);
  1173.  
  1174.             DeleteObject(SelectObject(hdc, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW))));
  1175.             Rectangle(hdc, 1, 1, rect.right - 1, rect.bottom - 1);
  1176.  
  1177.             DeleteObject(SelectObject(hdc, hpen));
  1178.             DeleteObject(SelectObject(hdc, hbrush));
  1179.  
  1180.             index = GetWindowWord(hwnd, 0);
  1181.  
  1182.             if (!ISKANJI(index) || index <= 0) {
  1183.                 EndPaint(hwnd, &ps);
  1184.                 return (0);
  1185.             }
  1186.  
  1187.             if (LargeFont == 0) {
  1188.                 /* Find out which font is the largest */
  1189.  
  1190.                 for (i = 0; i < global.nr_fonts; i++) {
  1191.                     if (i == 0) {
  1192.                         j = 0;
  1193.                         LargestArea = (long int) InstalledFonts[0].width * (long int) InstalledFonts[0].height;
  1194.                         continue;
  1195.                     }
  1196.                     area = (long int) InstalledFonts[i].width * (long int) InstalledFonts[i].height;
  1197.                     if (area > LargestArea) {
  1198.                         j = i;
  1199.                         LargestArea = area;
  1200.                     }
  1201.                 }
  1202.  
  1203.                 /* Try to open the font */
  1204.  
  1205.                 fd = OpenFile(InstalledFonts[j].filename, &of, OF_READ);
  1206.                 if (fd <= 0) {
  1207.                     ErrorMessage(hwnd, "Cannot open font file %s.  Using system font.",
  1208.                                     InstalledFonts[j].filename);
  1209.  
  1210.                     LargeFont = 2;
  1211.                     goto UseSystem;
  1212.                 }
  1213.  
  1214.                 lseek(fd, 0L, 0);
  1215.                 read(fd, &fh, sizeof(FONTHEADER));
  1216.                 LargeFont = 1;
  1217.                 goto UseLarge;
  1218.             } else if (LargeFont == 1) {
  1219.                 fd = OpenFile(NULL, &of, OF_READ | OF_REOPEN);
  1220.  
  1221. UseLarge:       width = fh.width;
  1222.                 height = fh.height;
  1223.  
  1224.                 offset = Jis2Index(index, fh.holes);
  1225.                 if (offset >= 0) {
  1226.                     offset *= fh.charsize;
  1227.                     offset += fh.offset;
  1228.  
  1229.                     lseek(fd, offset, 0);
  1230.                     read(fd, tempbuf, fh.charsize);
  1231.                     AllignKanjiBitmap(buffer, tempbuf, fh.charsize, height);
  1232.                 }
  1233.                 close(fd);
  1234.             } else {
  1235. UseSystem:      i = Jis2Index(index, SYSFONT->holes);
  1236.                 if (i >= 0) {
  1237.                     EnableFontCache(FALSE);
  1238.                     i = GetKanjiBitmap (SYSFONT, i, &cbufp);
  1239.                     EnableFontCache(TRUE);
  1240.                     width = SYSFONT->width;
  1241.                     height = SYSFONT->height;
  1242.                     _fmemcpy(buffer, cbufp, i);
  1243.                 }
  1244.             }
  1245.  
  1246.             hbitmap = CreateBitmap(width, height, 1, 1, buffer);
  1247.             hdcmem = CreateCompatibleDC(hdc);
  1248.             SelectObject(hdcmem, hbitmap);
  1249.             StretchBlt(hdc, KANJIBOXBORDER, KANJIBOXBORDER,
  1250.                         rect.right - 2 * KANJIBOXBORDER,
  1251.                         rect.bottom - 2 * KANJIBOXBORDER,
  1252.                         hdcmem, 0, 0, width, height, SRCCOPY);
  1253.             DeleteDC(hdcmem);
  1254.             DeleteObject(hbitmap);
  1255.             EndPaint(hwnd, &ps);
  1256.             return (0);
  1257.         }
  1258.  
  1259.         case WM_USER:
  1260.             wParam &= 0x7f7f;
  1261.  
  1262.             if (GetWindowWord(hwnd, 0) != wParam) {
  1263.                 SetWindowWord(hwnd, 0, wParam);
  1264.                 InvalidateRect(hwnd, NULL, TRUE);
  1265.                 UpdateWindow(hwnd);
  1266.             }
  1267.             return (0);
  1268.     }
  1269.  
  1270.     return (DefWindowProc(hwnd, message, wParam, lParam));
  1271. }
  1272.  
  1273.  
  1274.  
  1275. BOOL FAR PASCAL JISTableDlgProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  1276. {
  1277.     char tempbuf[5];
  1278.  
  1279.     switch (message) {
  1280.         case WM_INITDIALOG:
  1281.             PageNum = 0;
  1282.             SelRow = SelCol = -1;
  1283.             SetDlgItemInt(hwnd, 4221, 1, TRUE);
  1284.             SetDlgItemText(hwnd, 4222, "21");
  1285.             EnableWindow(GetDlgItem(hwnd, 4212), FALSE);
  1286.             EnableWindow(GetDlgItem(hwnd, 4213), FALSE);
  1287.             SetScrollRange(GetDlgItem(hwnd, 4201), SB_VERT, 0, 0x7e - 0x21 - 1, FALSE);
  1288.             SetScrollPos(GetDlgItem(hwnd, 4201), SB_VERT, 0, TRUE);
  1289.  
  1290.             if (global.active == NULL)
  1291.                 EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);    /* Insert button */
  1292.  
  1293.             CenterDialogBox(hwnd);
  1294.  
  1295.             /* RowPos and ColPos should have been set by JISTableProc   */
  1296.             /* already because child windows are sent WM_CREATE's first */
  1297.  
  1298.             if (RowPos < 2 || ColPos < 2) {
  1299.                 ErrorMessage(hwnd, "Your monitor currently does not have enough resolution to\n"
  1300.                                       "display the JIS Table.  You must either use a higher resolution\n"
  1301.                                       "video-mode, or select a lower-resolution system font.");
  1302.                 EndDialog(hwnd, FALSE);
  1303.             }
  1304.  
  1305.             return (TRUE);
  1306.  
  1307.         case WM_KEYDOWN:
  1308.             switch (wParam) {
  1309.                 case VK_NEXT:
  1310.                     if (PageNum + 0x21 >= 0x7e) return (TRUE);
  1311.                     if (PageNum <= 0)
  1312.                         EnableWindow(GetDlgItem(hwnd, 4212), TRUE);
  1313.                     PageNum++;
  1314.                     if (PageNum + 0x21 >= 0x7e)
  1315.                         EnableWindow(GetDlgItem(hwnd, 4211), FALSE);
  1316.                     break;
  1317.  
  1318.                 case VK_PRIOR:
  1319.                     if (PageNum <= 0) return (TRUE);
  1320.                     if (PageNum + 0x21 >= 0x7e)
  1321.                         EnableWindow(GetDlgItem(hwnd, 4211), TRUE);
  1322.                     PageNum--;
  1323.                     if (PageNum <= 0)
  1324.                         EnableWindow(GetDlgItem(hwnd, 4212), FALSE);
  1325.                     break;
  1326.  
  1327.                 case VK_END:
  1328.                     if (PageNum <= 0)
  1329.                         EnableWindow(GetDlgItem(hwnd, 4212), TRUE);
  1330.                     PageNum = 0x7e - 0x21 - 1;
  1331.                     EnableWindow(GetDlgItem(hwnd, 4211), FALSE);
  1332.                     break;
  1333.  
  1334.                 case VK_HOME:
  1335.                     if (PageNum + 0x21 >= 0x7e)
  1336.                         EnableWindow(GetDlgItem(hwnd, 4211), TRUE);
  1337.                     PageNum = 0;
  1338.                     EnableWindow(GetDlgItem(hwnd, 4212), FALSE);
  1339.                     break;
  1340.  
  1341.                 case VK_SELECT:
  1342.                     PageNum = LOWORD(lParam);
  1343.                     EnableWindow(GetDlgItem(hwnd, 4211), PageNum + 0x21 < 0x7e);
  1344.                     EnableWindow(GetDlgItem(hwnd, 4212), PageNum > 0);
  1345.                     break;
  1346.  
  1347.                 default: return (0);
  1348.             }
  1349.  
  1350.             SelRow = SelCol = -1;
  1351.             EnableWindow(GetDlgItem(hwnd, 4213), FALSE);
  1352.             SetDlgItemInt(hwnd, 4221, PageNum + 1, TRUE);
  1353.             SetScrollPos(GetDlgItem(hwnd, 4201), SB_VERT, PageNum, TRUE);
  1354.             sprintf(tempbuf, "%X", PageNum + 0x21);
  1355.             SetDlgItemText(hwnd, 4222, tempbuf);
  1356.             InvalidateRect(GetDlgItem(hwnd, 4201), NULL, FALSE);
  1357.             return (FALSE);
  1358.  
  1359.         case WM_COMMAND:
  1360.             switch (wParam) {
  1361.                 case 4211:          /* Next button */
  1362.                     SendDlgItemMessage(hwnd, 4201, WM_KEYDOWN, VK_NEXT, 0L);
  1363.                     return (TRUE);
  1364.  
  1365.                 case 4212:          /* Prev button */
  1366.                     SendDlgItemMessage(hwnd, 4201, WM_KEYDOWN, VK_PRIOR, 0L);
  1367.                     return (TRUE);
  1368.  
  1369.                 case 4213: {        /* Info button */
  1370.                     KANJI ch;
  1371.  
  1372.                     if (SelRow < 0 || SelCol < 0) {
  1373.                         MessageBeep(0);
  1374.                         return (TRUE);
  1375.                     }
  1376.  
  1377.                     ch = ((SelRow + 2) << 4) | SelCol;
  1378.                     ch |= ((PageNum + 0x21) << 8);
  1379.  
  1380.                     SetKanjiInfoChar(ch);
  1381.  
  1382.                     DialogBox (hInstance, "KanjiInfo", hwnd, KanjiInfoProc);
  1383.                     return (TRUE);
  1384.                 }
  1385.  
  1386.                 case IDOK: {        /* Insert button */
  1387.                     KANJI buf[2];
  1388.  
  1389.                     if (curfile != NULL && SelRow >= 0 && SelCol >= 0) {
  1390.                         buf[0] = ((SelRow + 2) << 4) | SelCol;
  1391.                         buf[0] |= ((PageNum + 0x21) << 8);
  1392.                         buf[1] = 0;
  1393.  
  1394.                         TurnOffSelection(curfile);
  1395.                         UndoAddTyping(curfile, curfile->current, 1, FALSE);
  1396.                         InsertString(curfile, curfile->current, buf,
  1397.                                 OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND);
  1398.                     }
  1399.                     EndDialog(hwnd, FALSE);
  1400.                     return (TRUE);
  1401.                 }
  1402.  
  1403.                 case IDCANCEL:
  1404.                     EndDialog(hwnd, FALSE);
  1405.                     return (TRUE);
  1406.             }
  1407.             return (FALSE);
  1408.     }
  1409.  
  1410.     return (FALSE);
  1411. }
  1412.  
  1413.  
  1414.  
  1415. static BOOL FindNextChar (int page, int *row, int *col, BOOL hori, int step)
  1416. {
  1417.     int x, y, r;
  1418.     KANJI index;
  1419.  
  1420.     y = *row;
  1421.     x = *col;
  1422.  
  1423.     for (; ; ) {
  1424.         if (hori) {
  1425.             x += step;
  1426.  
  1427.             if (x >= 16) {
  1428.                 x = 0; y++;
  1429.                 if (y >= NRJISROWS) return (FALSE);
  1430.             }
  1431.             if (x < 0) {
  1432.                 x = 15; y--;
  1433.                 if (y < 0) return (FALSE);
  1434.             }
  1435.         } else {
  1436.             y += step;
  1437.  
  1438.             if (y >= NRJISROWS) {
  1439.                 y = 0; x++;
  1440.                 if (x >= 16) return (FALSE);
  1441.             }
  1442.             if (y < 0) {
  1443.                 y = NRJISROWS - 1; x--;
  1444.                 if (x < 0) return (FALSE);
  1445.             }
  1446.         }
  1447.  
  1448.         index = ((y + 2) << 4) | x;
  1449.         index |= ((page + 0x21) << 8);
  1450.  
  1451.         r = Jis2Index(index, SYSFONT->holes);
  1452.  
  1453.         if (r >= 0) {
  1454.             *row = y;
  1455.             *col = x;
  1456.             return (TRUE);
  1457.         }
  1458.     }
  1459. }
  1460.  
  1461.  
  1462.  
  1463. LONG FAR PASCAL JISTableProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  1464. {
  1465.     int i, j, r;
  1466.     KANJI index;
  1467.     HDC hdc;
  1468.     PAINTSTRUCT ps;
  1469.     RECT rect;
  1470.     HBRUSH hbrush;
  1471.     HPEN hpen;
  1472.     BYTE far *cbufp;
  1473.     static int capturing;
  1474.  
  1475.     switch (message) {
  1476.         case WM_CREATE:
  1477.             SetScrollRange(GetDlgItem(hwnd, 4201), SB_VERT, 0, 0x7e - 0x21 - 1, TRUE);
  1478.             SetScrollPos(GetDlgItem(hwnd, 4201), SB_VERT, 0, TRUE);
  1479.  
  1480.             GetClientRect(hwnd, &rect);
  1481.             RowDiv = rect.bottom / NRJISROWS;
  1482.             ColDiv = rect.right / 16;
  1483.  
  1484.             i = RowDiv * NRJISROWS;
  1485.             j = ColDiv * 16 + GetSystemMetrics(SM_CXVSCROLL);
  1486.  
  1487.             SetWindowPos(hwnd, NULL, 0, 0, j + 1, i + 1, SWP_NOMOVE | SWP_NOZORDER);
  1488.  
  1489.             RowPos = (RowDiv - SYSFONT->height) / 2;
  1490.             ColPos = (ColDiv - SYSFONT->width) / 2;
  1491.  
  1492.             capturing = FALSE;
  1493.  
  1494.             return (0);
  1495.  
  1496.         case WM_GETDLGCODE:
  1497.             return (DLGC_WANTARROWS);
  1498.  
  1499.         case WM_VSCROLL:
  1500.             switch (wParam) {
  1501.                 case SB_TOP:
  1502.                     SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_HOME, 0L);
  1503.                     break;
  1504.  
  1505.                 case SB_BOTTOM:
  1506.                     SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_END, 0L);
  1507.                     break;
  1508.  
  1509.                 case SB_PAGEUP:
  1510.                 case SB_LINEUP:
  1511.                     SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_PRIOR, 0L);
  1512.                     break;
  1513.  
  1514.                 case SB_PAGEDOWN:
  1515.                 case SB_LINEDOWN:
  1516.                     SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_NEXT, 0L);
  1517.                     break;
  1518.  
  1519.                 case SB_THUMBPOSITION:
  1520.                     SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_SELECT, LOWORD(lParam));
  1521.                     break;
  1522.  
  1523.                 case SB_THUMBTRACK: {
  1524.                     char tempbuf[10];
  1525.  
  1526.                     i = LOWORD(lParam);
  1527.                     SetDlgItemInt(GetParent(hwnd), 4221, i + 1, TRUE);
  1528.                     sprintf(tempbuf, "%X", i + 0x21);
  1529.                     SetDlgItemText(GetParent(hwnd), 4222, tempbuf);
  1530.                     break;
  1531.                 }
  1532.  
  1533.             }
  1534.             return (0);
  1535.  
  1536.         case WM_KEYDOWN:
  1537.             switch (wParam) {
  1538.                 case VK_NEXT:
  1539.                 case VK_PRIOR:
  1540.                 case VK_HOME:
  1541.                 case VK_END:
  1542.                 case VK_SELECT:
  1543.                     SendMessage(GetParent(hwnd), WM_KEYDOWN, wParam, lParam);
  1544.                     return (0);
  1545.  
  1546.                 case VK_UP:
  1547.                 case VK_DOWN:
  1548.                 case VK_LEFT:
  1549.                 case VK_RIGHT: {
  1550.                     BOOL hori;
  1551.                     int step;
  1552.  
  1553.                     if (wParam == VK_UP || wParam == VK_DOWN) hori = FALSE;
  1554.                     else hori = TRUE;
  1555.  
  1556.                     if (wParam == VK_UP || wParam == VK_LEFT) step = -1;
  1557.                     else step = +1;
  1558.  
  1559.                     i = SelCol;
  1560.                     j = SelRow;
  1561.  
  1562.                     if (i < 0 || j < 0) {
  1563.                         j = 0; i = -1;
  1564.                         hori = TRUE;
  1565.                         step = +1;
  1566.                     }
  1567.  
  1568.                     if (!FindNextChar(PageNum, &j, &i, hori, step)) {
  1569.                         MessageBeep(0);
  1570.                         return (0);
  1571.                     }
  1572.  
  1573.                     SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELONG((i * ColDiv), (j * RowDiv)));
  1574.                     return (0);
  1575.                 }
  1576.  
  1577.                 case VK_ESCAPE:
  1578.                     SendMessage(GetParent(hwnd), WM_COMMAND, IDCANCEL, lParam);
  1579.                     return (0);
  1580.             }
  1581.             break;
  1582.  
  1583.         case WM_LBUTTONDBLCLK:
  1584.             if (SelRow >= 0 && SelCol >= 0) {
  1585.                 SendMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0L);
  1586.             } else {
  1587.                 MessageBeep(0);
  1588.             }
  1589.             return (0);
  1590.  
  1591.         case WM_LBUTTONDOWN:
  1592.             i = LOWORD(lParam);
  1593.             j = HIWORD(lParam);
  1594.  
  1595.             GetClientRect(hwnd, &rect);
  1596.  
  1597.             i /= ColDiv;
  1598.             j /= RowDiv;
  1599.  
  1600.             if (j < 0 || j >= NRJISROWS || i < 0 || i >= 16) return (0);
  1601.  
  1602.             index = ((j + 2) << 4) | i;
  1603.             index |= ((PageNum + 0x21) << 8);
  1604.  
  1605.             r = Jis2Index(index, SYSFONT->holes);
  1606.  
  1607.             if (r < 0) {
  1608.                 MessageBeep(0);
  1609.                 return (0);
  1610.             }
  1611.  
  1612.             hdc = GetDC(hwnd);
  1613.  
  1614.             SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  1615.             SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  1616.  
  1617.             if (SelRow >= 0 && SelCol >= 0) {
  1618.                 if (i != SelCol || j != SelRow) {
  1619.                     PatBlt(hdc, SelCol * ColDiv + 1, SelRow * RowDiv + 1,
  1620.                            ColDiv - 1, RowDiv - 1, DSTINVERT);
  1621.                     SelCol = i; SelRow = j;
  1622.                 } else {
  1623.                     SelRow = SelCol = -1;
  1624.                 }
  1625.             } else {
  1626.                 SelCol = i; SelRow = j;
  1627.             }
  1628.  
  1629.             PatBlt(hdc, i * ColDiv + 1, j * RowDiv + 1, ColDiv - 1, RowDiv - 1, DSTINVERT);
  1630.             ReleaseDC(hwnd, hdc);
  1631.  
  1632.             if (SelRow >= 0 && SelCol >= 0) {
  1633.                 index = ((SelRow + 2) << 4) | SelCol;
  1634.                 index |= ((PageNum + 0x21) << 8);
  1635.  
  1636.                 if (ISKANJI(index)) {
  1637.                     EnableWindow(GetDlgItem(GetParent(hwnd), 4213), TRUE);
  1638.                 } else {
  1639.                     EnableWindow(GetDlgItem(GetParent(hwnd), 4213), FALSE);
  1640.                 }
  1641.             } else {
  1642.                 EnableWindow(GetDlgItem(GetParent(hwnd), 4213), FALSE);
  1643.             }
  1644.  
  1645.             return (0);
  1646.  
  1647.         case WM_PAINT:
  1648.             hdc = BeginPaint(hwnd, &ps);
  1649.  
  1650.             SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  1651.             SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  1652.             hbrush = SelectObject(hdc, CreateSolidBrush(GetSysColor(COLOR_WINDOW)));
  1653.             hpen = SelectObject(hdc, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME)));
  1654.  
  1655.             GetClientRect(hwnd, &rect);
  1656.             Rectangle(hdc, 0, 0, rect.right, rect.bottom);
  1657.  
  1658.             DeleteObject(SelectObject(hdc, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW))));
  1659.  
  1660.             for (i = 1; i < NRJISROWS + 1; i++) {
  1661.                 MoveTo(hdc, 1, i * RowDiv - 1);
  1662.                 LineTo(hdc, rect.right - 1, i * RowDiv - 1);
  1663.             }
  1664.  
  1665.             for (i = 1; i <= 16; i++) {
  1666.                 MoveTo(hdc, i * ColDiv - 1, 1);
  1667.                 LineTo(hdc, i * ColDiv - 1, rect.bottom - 1);
  1668.             }
  1669.  
  1670.             DeleteObject(SelectObject(hdc, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME))));
  1671.  
  1672.             for (i = 1; i < NRJISROWS; i++) {
  1673.                 MoveTo(hdc, 0, i * RowDiv);
  1674.                 LineTo(hdc, rect.right, i * RowDiv);
  1675.             }
  1676.  
  1677.             for (i = 1; i < 16; i++) {
  1678.                 MoveTo(hdc, i * ColDiv, 0);
  1679.                 LineTo(hdc, i * ColDiv, rect.bottom);
  1680.             }
  1681.  
  1682.             EnableFontCache(FALSE);
  1683.  
  1684.             for (i = 0; i < NRJISROWS; i++) {
  1685.                 for (j = 0; j < 16; j++) {
  1686.                     index = ((i + 2) << 4) | j;
  1687.                     index |= ((PageNum + 0x21) << 8);
  1688.  
  1689.                     r = Jis2Index(index, SYSFONT->holes);
  1690.  
  1691.                     if (r < 0) {
  1692.                         rect.left = j * ColDiv + 1;
  1693.                         rect.top = i * RowDiv + 1;
  1694.                         rect.right = j * ColDiv + ColDiv + 1;
  1695.                         rect.bottom = i * RowDiv + RowDiv + 1;
  1696.                         FillRect(hdc, &rect, GetStockObject(GRAY_BRUSH));
  1697.                         continue;
  1698.                     }
  1699.  
  1700.                     r = GetKanjiBitmap(SYSFONT, r, &cbufp);
  1701.                     DisplayKanjiBitmap(hdc, j * ColDiv + ColPos,
  1702.                                         i * RowDiv + SYSFONT->height + RowPos,
  1703.                                         SYSFONT->width, SYSFONT->height,
  1704.                                         r, SRCCOPY, cbufp);
  1705.  
  1706.                     if (i == SelRow && j == SelCol) {
  1707.                         PatBlt(hdc, j * ColDiv + 1, i * RowDiv + 1,
  1708.                                 ColDiv - 1, RowDiv - 1, DSTINVERT);
  1709.                     }
  1710.                 }
  1711.             }
  1712.  
  1713.             EnableFontCache(TRUE);
  1714.  
  1715.             DeleteObject(SelectObject(hdc, hbrush));
  1716.             DeleteObject(SelectObject(hdc, hpen));
  1717.  
  1718.             EndPaint(hwnd, &ps);
  1719.             return (0);
  1720.     }
  1721.  
  1722.     return (DefWindowProc(hwnd, message, wParam, lParam));
  1723. }
  1724.