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

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3.  
  4. #include "jwp.h"
  5.  
  6. #include "idm.h"
  7.  
  8.  
  9. #define DICTINDENT   5
  10. #define NRCACHE      20
  11.  
  12. typedef struct {
  13.     long int offset;
  14.     KANJI far *string;
  15. } DICTCACHE;
  16.  
  17.  
  18. static BOOL DictOK = FALSE;
  19. static OFSTRUCT dictof, idxof;
  20. static DICTCACHE cache[NRCACHE];
  21.  
  22.  
  23.  
  24.  
  25. static KANJI far *ConvertOffset (int id, LONG lParam, KANJI *buf)
  26. {
  27.     FILE *fp;
  28.     int fd, i, j, ch;
  29.     long int offset;
  30.     int length;
  31.  
  32.     length = (lParam >> 24) & 0x00ff;
  33.     offset = lParam & 0x00ffffff;
  34.  
  35.     /* In the cache? */
  36.  
  37.     for (i = 0; i < NRCACHE; i++) {
  38.         if (cache[i].string == NULL) continue;
  39.         if (cache[i].offset == offset) break;
  40.     }
  41.  
  42.     if (i < NRCACHE) return (cache[i].string);
  43.  
  44.  
  45.     /* Not in the cache */
  46.  
  47.     buf[0] = 0;
  48.  
  49.     fd = OpenFile(NULL, &dictof, OF_READ | OF_REOPEN);
  50.  
  51.     fp = fdopen(fd, "rb");
  52.     if (fp == NULL) {
  53.         close(fd);
  54.         return ((KANJI far *) buf);
  55.     }
  56.  
  57.     fseek(fp, offset, 0);
  58.  
  59.     for (i = j = 0; j < length; i++) {
  60.         ch = getc(fp);
  61.         j++;
  62.  
  63.         if (ch & 0x80) {
  64.             ch &= 0x007f;
  65.             buf[i] = (ch << 8) | (getc(fp) & 0x007f);
  66.             j++;
  67.         } else if (ch == '/') {
  68.             buf[i++] = ',';
  69.             buf[i] = ' ';
  70.         } else {
  71.             buf[i] = ch;
  72.         }
  73.     }
  74.  
  75.     buf[i] = 0;
  76.     fclose(fp);
  77.  
  78.     if (i <= 0) {
  79.         return ((KANJI far *) buf);
  80.     } else if (!ISKANJI(buf[0])) {
  81.         for (; i >= 0; i--) buf[i+DICTINDENT] = buf[i];
  82.         for (i = 0; i < DICTINDENT; i++) buf[i] = ' ';
  83.     } else {
  84.         for (i = 0; buf[i] != 0; i++) {
  85.             if (buf[i] == '[') buf[i] = 0x215a;
  86.             else if (buf[i] == ']') buf[i] = 0x215b;
  87.             else if (buf[i] == ' ') buf[i] = 0x2121;
  88.         }
  89.     }
  90.  
  91.  
  92.     /* Put in the cache */
  93.  
  94.     for (i = 0; i < NRCACHE && cache[i].string != NULL; i++);
  95.     if (i >= NRCACHE) {
  96.         long int diff, maxdiff;
  97.  
  98.         for (i = maxdiff = 0, j = -1; i < NRCACHE; i++) {
  99.             diff = cache[i].offset - offset;
  100.             if (diff < 0) diff = -diff;
  101.             if (diff > maxdiff) {
  102.                 j = i;
  103.                 maxdiff = diff;
  104.             }
  105.         }
  106.         if (j < 0) j = rand() % NRCACHE;
  107.         i = j;
  108.     }
  109.  
  110.     if (cache[i].string != NULL) FreeBlock(cache[i].string);
  111.     cache[i].string = (KANJI far *) BlockAlloc((kanjilen(buf) + 5) * sizeof(KANJI));
  112.     cache[i].offset = offset;
  113.     kanjicpy(cache[i].string, buf);
  114.  
  115.     return ((KANJI far *) buf);
  116. }
  117.  
  118.  
  119.  
  120. static BOOL CheckDictionary (void)
  121. {
  122.     int fd;
  123.     long int indexsize;
  124.     long int dictsize;
  125.  
  126.  
  127.     if (DictOK) return (TRUE);
  128.  
  129.     for (;;) {
  130.         fd = OpenFile(global.jdict, &dictof, OF_READ);
  131.         if (fd >= 0) break;
  132.         if (!RetryMessage ("Cannot open dictionary '%s'!", global.jdict))
  133.             return (FALSE);
  134.     }
  135.     lseek(fd, 0L, 2);
  136.     dictsize = tell(fd);
  137.     close(fd);
  138.  
  139.     for (;;) {
  140.         fd = OpenFile(global.jdictidx, &idxof, OF_READ);
  141.         if (fd >= 0) break;
  142.         if (!RetryMessage ("Cannot open dictionary index '%s'!", global.jdictidx))
  143.             return (FALSE);
  144.     }
  145.  
  146.     lseek(fd, 0L, 0);
  147.     read(fd, &indexsize, sizeof(long int));
  148.     close(fd);
  149.  
  150.     if (indexsize != dictsize + 15) {
  151.         ErrorMessage(global.hwnd, "This index file does not belong to this dictionary!");
  152.         return (FALSE);
  153.     }
  154.  
  155.     DictOK = TRUE;
  156.  
  157.     return (TRUE);
  158. }
  159.  
  160.  
  161.  
  162. static int DictComp (BYTE *p1, BYTE *p2, int n)
  163. {
  164.     int i;
  165.     BYTE c1, c2;
  166.     BOOL f1 = FALSE, f2 = FALSE;
  167.  
  168.     for (i = 0; ; i++, p1++, p2++) {
  169.         if (n > 0 && i >= n) return (0);
  170.  
  171.         c1 = *p1;
  172.         c2 = *p2;
  173.  
  174.         if ('A' <= c1 && c1 <= 'Z') c1 += 32;
  175.         if ('A' <= c2 && c2 <= 'Z') c2 += 32;
  176.  
  177.         if (c1 & 0x80) {
  178.             f1 = !f1;
  179.             if (f1 && c1 == 0xa5) c1 = 0xa4;        /* Katakana? */
  180.         } else {
  181.             f1 = FALSE;
  182.         }
  183.         if (c2 & 0x80) {
  184.             f2 = !f2;
  185.             if (f2 && c2 == 0xa5) c2 = 0xa4;        /* Katakana? */
  186.         } else {
  187.             f2 = FALSE;
  188.         }
  189.  
  190.         if (c1 != c2) return (c1 - c2);
  191.         if (c1 == 0) return (0);
  192.     }
  193.  
  194.     return (c1 - c2);
  195. }
  196.  
  197.  
  198.  
  199. static int SearchDictionary (HWND DlgHwnd, HWND KeyHwnd, HWND ListHwnd)
  200. {
  201.     int i, j, k, last, len;
  202.     int fd, nr_matches;
  203.     BOOL PassedKanji, Duplicate;
  204.     FILE *fp;
  205.     long int nr_index;
  206.     long int top, bottom, middle;
  207.     long int offset, cut, temp;
  208.     int diff, length;
  209.     MSG msg;
  210.     BYTE key[MAXLINELEN], target[MAXLINELEN];
  211.     KANJI ch;
  212.     UNIT far *up;
  213.     RECT rect;
  214.  
  215.  
  216.     /* Deletes everything from the list box */
  217.     if (SendMessage(ListHwnd, LB_GETCOUNT, 0, 0L) > 0)
  218.         SendMessage(ListHwnd, LB_RESETCONTENT, 0, 0L);
  219.  
  220.     while (PeekMessage(&msg, DlgHwnd, 0, 0, PM_REMOVE)) {
  221.         TranslateMessage(&msg);
  222.         DispatchMessage(&msg);
  223.     }
  224.  
  225.  
  226.     /* Opens the dictionary and index files */
  227.  
  228.     fd = OpenFile(NULL, &dictof, OF_READ | OF_REOPEN);
  229.     if (fd < 0) return (0);
  230.  
  231.     fp = fdopen(fd, "rb");
  232.     if (fp == NULL) {
  233.         close(fd);
  234.         return (0);
  235.     }
  236.  
  237.     fd = OpenFile(NULL, &idxof, OF_READ | OF_REOPEN);
  238.     if (fd < 0) {
  239.         fclose(fp);
  240.         return (0);
  241.     }
  242.  
  243.     lseek(fd, 0L, 2);       /* Move to EOF */
  244.  
  245.     nr_index = (tell(fd) / sizeof(long int)) - 1;
  246.     nr_matches = 0;
  247.  
  248.  
  249.     /* Create the key string */
  250.  
  251.     up = (UNIT far *) SendMessage(KeyHwnd, EM_GETLINE, 0, 0L);
  252.  
  253.     for (i = j = 0; ; j++) {
  254.         ch = up[j].kanji;
  255.         if (ch == 0) break;
  256.  
  257.         if (ISKANJI(ch)) {
  258.             key[i++] = HIBYTE(ch) | 0x0080;
  259.             key[i++] = LOBYTE(ch) | 0x0080;
  260.         } else {
  261.             key[i++] = ch;
  262.         }
  263.     }
  264.  
  265.     key[i] = '\0';
  266.     length = i;
  267.  
  268.  
  269.  
  270.     /* Binary Search */
  271.  
  272.     top = 0;
  273.     bottom = nr_index - 1;
  274.  
  275.     for (;;) {
  276.         middle = (top + bottom) / 2;
  277.  
  278.         /* Get the offset */
  279.  
  280.         lseek(fd, (middle + 1) * sizeof(long int), 0);
  281.         read(fd, &offset, sizeof(long int));
  282.  
  283.  
  284.         /* Get the target string */
  285.  
  286.         fseek(fp, offset - 1, 0);
  287.         fgets(target, MAXLINELEN, fp);
  288.  
  289.         diff = DictComp(key, target, -1);
  290.  
  291.         if (diff == 0) {
  292.             cut = middle;
  293.             break;
  294.         }
  295.  
  296.         if (top >= bottom - 1) {
  297.             cut = bottom;
  298.             break;
  299.         }
  300.  
  301.         if (diff > 0) top = middle;
  302.         else bottom = middle;
  303.     }
  304.  
  305.     SendMessage(ListHwnd, WM_SETREDRAW, FALSE, 0L);
  306.     GetClientRect(ListHwnd, &rect);
  307.     rect.right -= 2 * GetSystemMetrics(SM_CXVSCROLL);
  308.  
  309.  
  310.     for (;; cut++) {
  311.         /* Now, did the user abort? */
  312.  
  313.         if (PeekMessage(&msg, DlgHwnd, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) {
  314.             if (msg.message == WM_CHAR && msg.wParam == '\x1b') {
  315.                 if (YesNo(DlgHwnd, "Dictionary search interrupted!\n\nContinue?") != IDYES) break;
  316.             } else {
  317.                 TranslateMessage(&msg);
  318.             }
  319.             //DispatchMessage(&msg);
  320.         }
  321.  
  322.         lseek(fd, (cut + 1) * sizeof(long int), 0);
  323.         read(fd, &offset, sizeof(long int));
  324.  
  325.         /* Get the text string */
  326.  
  327.         offset--;
  328.         fseek(fp, offset, 0);
  329.         fgets(target, MAXLINELEN, fp);
  330.  
  331.  
  332.         /* Still matches? */
  333.  
  334.         if (DictComp(key, target, length)) break;
  335.         nr_matches++;
  336.  
  337.         if (nr_matches > 0) {
  338.             char tempbuf[50];
  339.  
  340.             sprintf(tempbuf, "%d match%s", nr_matches, (nr_matches > 1) ? "es" : "");
  341.             SetDlgItemText(GetParent(KeyHwnd), 4202, tempbuf);
  342.         }
  343.  
  344.  
  345.         /* OK, now backseek to the beginning of the line, shall we? */
  346.  
  347.         fseek(fp, offset, 0);
  348.  
  349.         for (;;) {
  350.             if (offset < MAXLINELEN) {
  351.                 fseek(fp, 0L, 0);
  352.                 j = offset;
  353.                 offset = 0L;
  354.             } else {
  355.                 fseek(fp, -MAXLINELEN, 1);      /* Get the previous block */
  356.                 j = MAXLINELEN;
  357.                 offset -= MAXLINELEN;
  358.             }
  359.             fread(target, sizeof(BYTE), MAXLINELEN, fp);
  360.  
  361.             for(i = j - 1; i >= 0; i--) {
  362.                 if (target[i] == '\n' || target[i] == '\r') break;
  363.             }
  364.  
  365.             if (i > 0) {
  366.                 i++;
  367.                 offset += i;
  368.                 break;
  369.             }
  370.  
  371.             if (offset <= 0L) break;
  372.         }
  373.  
  374.  
  375.         fseek(fp, offset, 0);
  376.         fgets(target, MAXLINELEN, fp);
  377.  
  378.         for (i = strlen(target) - 1; i >= 0; i--) {
  379.             if (target[i] != '\n' && target[i] != '\r' && target[i] != '/') break;
  380.         }
  381.         target[i+1] = '\0';
  382.  
  383.  
  384.         /* Is it in the dictionary already? */
  385.  
  386.         Duplicate = FALSE;
  387.         len = SendMessage(ListHwnd, LB_GETCOUNT, 0, 0L);
  388.  
  389.         for (i = 0; i < len; i++) {
  390.             temp = (long int) SendMessage(ListHwnd, LB_GETITEMDATA, i, 0L);
  391.             temp &= 0x00ffffff;
  392.             if (offset == temp) {
  393.                 Duplicate = TRUE;
  394.                 break;
  395.             }
  396.         }
  397.  
  398.         if (Duplicate) continue;
  399.  
  400.  
  401.         /* Now break it down into individual lines */
  402.  
  403.         last = -1;
  404.         PassedKanji = FALSE;
  405.  
  406.  
  407.         for (i = j = k = 0; ; i++) {
  408.             if (FALSE) {
  409.                 if (!target[i]) break;
  410.  
  411.                 if (target[i] == '/') {
  412.                     SendMessage(ListHwnd, LB_ADDSTRING, 0,
  413.                             (offset & 0x00ffffff) | (((LONG) j) << 24));
  414.                     offset += (j + 1);
  415.                     j = 0;
  416.                 } else {
  417.                     j++;
  418.                 }
  419.             } else {
  420.                 if (target[i] <= ' ' || target[i] == '/') last = j;
  421.  
  422.                 if (target[i]) {
  423.                     if (target[i] == '/') {
  424.                         if (!PassedKanji) {
  425.                             SendMessage(ListHwnd, LB_ADDSTRING, 0,
  426.                                         (offset & 0x00ffffff) | (((LONG) j) << 24));
  427.                             offset += (j + 1);
  428.                             j = 0;
  429.                             k = DICTINDENT * FontCharWidth(' ', 0);     /* System font */
  430.                             PassedKanji = TRUE;
  431.                             continue;
  432.                         }
  433.                         k += FontCharWidth(',', 0);     /* System font */
  434.                         k += FontCharWidth(' ', 0);     /* System font */
  435.                     } else {
  436.                         k += FontCharWidth(target[i], 0);   /* System font */
  437.                     }
  438.                 }
  439.  
  440.                 if (!target[i]) {
  441.                     SendMessage(ListHwnd, LB_ADDSTRING, 0,
  442.                             (offset & 0x00ffffff) | (((LONG) j) << 24));
  443.                     break;
  444.                 } else if (PassedKanji && k >= rect.right) {
  445.                     SendMessage(ListHwnd, LB_ADDSTRING, 0,
  446.                             (offset & 0x00ffffff) | (((LONG) last + 1) << 24));
  447.  
  448.                     offset += (last + 1);
  449.                     i -= (j - last);
  450.                     j = 0;
  451.                     k = DICTINDENT * FontCharWidth(' ', 0);     /* System font */
  452.                 } else {
  453.                     j++;
  454.                 }
  455.             }
  456.         }
  457.     }
  458.  
  459.     SendMessage(ListHwnd, WM_SETREDRAW, TRUE, 0L);
  460.     InvalidateRect(ListHwnd, NULL, TRUE);
  461.  
  462.     fclose(fp);
  463.     close(fd);
  464.     return (nr_matches);
  465. }
  466.  
  467.  
  468.  
  469. LONG FAR PASCAL InputModeIconProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  470. {
  471.     HDC hdc, hdcmem;
  472.     HBITMAP hbitmap;
  473.     PAINTSTRUCT ps;
  474.     HWND hwnd1;
  475.  
  476.     switch (message) {
  477.         case EM_SETHANDLE:
  478.             SetWindowWord(hwnd, 0, wParam);
  479.             return (0);
  480.  
  481.         case WM_LBUTTONDOWN: {
  482.             FILEOPTIONS *f;
  483.  
  484.             hwnd1 = (HWND) GetWindowWord(hwnd, 0);
  485.             f = (FILEOPTIONS *) SendMessage(hwnd1, EM_GETHANDLE, 0, 0L);
  486.             if (f->type & FN_EITHER) SendMessage(hwnd1, EM_REPLACESEL, 0, (LONG) NULL);
  487.             SendMessage(hwnd1, WM_COMMAND, IDM_TOGGLEMODE, 0L);
  488.             InvalidateRect(hwnd, NULL, FALSE);
  489.             return (0);
  490.         }
  491.  
  492.         case WM_PAINT:
  493.             SetWindowPos(hwnd, NULL, 0, 0, 24, 24, SWP_NOMOVE | SWP_NOZORDER);
  494.  
  495.             /* Put in the bitmap */
  496.             hdc = BeginPaint(hwnd, &ps);
  497.             hdcmem = CreateCompatibleDC(hdc);
  498.  
  499.             switch (global.mode) {
  500.                 case M_ASCII: hbitmap = LoadBitmap(hInstance, "ASCIIBmp"); break;
  501.  
  502.                 default:
  503.                 case M_KANA:  hbitmap = LoadBitmap(hInstance, "KanaBmp"); break;
  504.             }
  505.  
  506.             SelectObject(hdcmem, hbitmap);
  507.             BitBlt(hdc, 0, 0, 24, 24, hdcmem, 0, 0, SRCCOPY);
  508.             DeleteDC(hdcmem);
  509.             DeleteObject(hbitmap);
  510.             EndPaint(hwnd, &ps);
  511.             return (0);
  512.     }
  513.  
  514.     return (DefWindowProc(hwnd, message, wParam, lParam));
  515. }
  516.  
  517.  
  518.  
  519. BOOL FAR PASCAL DictionaryProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  520. {
  521.     switch (message) {
  522.  
  523.         case WM_INITDIALOG: {
  524.             int i, len;
  525.             BOOL IsKanji1, IsKanji2;
  526.             KANJI buf[MAXLINELEN];
  527.             FILEOPTIONS *f, *f1;
  528.  
  529.             if (!CheckDictionary()) {
  530.                 EndDialog(hwnd, FALSE);
  531.                 return (TRUE);
  532.             }
  533.  
  534.             /* Set the type and mode-change icon of the Jedit control */
  535.             SendDlgItemMessage(hwnd, 4201, EM_SETMODIFY, FN_CONTROL | FN_EITHER, 0L);
  536.             SendDlgItemMessage(hwnd, 4201, EM_SETRECT, GetDlgItem(hwnd, 4231), 0L);
  537.  
  538.             f = (FILEOPTIONS *) SendDlgItemMessage(hwnd, 4201, EM_GETHANDLE, 0, 0L);
  539.  
  540.             SendDlgItemMessage(hwnd, 4231, EM_SETHANDLE, f->hwnd, 0L);  /* icon-change */
  541.  
  542.             if (global.active != NULL) f1 = global.active;
  543.  
  544.             if (global.active == NULL || SELPARA1(f1) == NULL) {
  545.                 if (global.mode != M_ASCII) ToggleInputMode();
  546.             } else {
  547.                 /* Copy the selected text */
  548.  
  549.                 if (SELPARA1(f1) != SELPARA2(f1)) {
  550.                     len = unitlen(SELPARA1(f1)->text) - SELPOS1(f1);
  551.                 } else {
  552.                     len = SELPOS2(f1) - SELPOS1(f1) + 1;
  553.                 }
  554.  
  555.                 IsKanji1 = ISKANJI(SELPARA1(f1)->text[SELPOS1(f1)].kanji);
  556.  
  557.                 for (i = 0; i < len; i++) {
  558.                     buf[i] = SELPARA1(f1)->text[SELPOS1(f1)+i].kanji;
  559.                     IsKanji2 = ISKANJI(buf[i]);
  560.                     if (IsKanji1 && !IsKanji2) break;
  561.                     if (!IsKanji1 && IsKanji2) break;
  562.                 }
  563.                 buf[i] = 0;
  564.  
  565.                 SendDlgItemMessage(hwnd, 4201, EM_REPLACESEL, 0, (LONG) buf);
  566.  
  567.                 if (len > 0) {
  568.                     SendDlgItemMessage(hwnd, 4201, EM_SETSEL, len, MAKELONG(0, len - 1));
  569.                 }
  570.             }
  571.  
  572.             EnableWindow(GetDlgItem(hwnd, 4212), FALSE);
  573.             EnableWindow(GetDlgItem(hwnd, 4211), (f->nr_bytes > 0));
  574.  
  575.             for (i = 0; i < NRCACHE; i++) cache[i].string = NULL;
  576.  
  577.             SetFocus(GetDlgItem(hwnd, 4201));
  578.  
  579.             CenterDialogBox(hwnd);
  580.  
  581.             return (TRUE);
  582.         }
  583.  
  584.         case WM_PAINT: {
  585.             HDC hdc;
  586.             PAINTSTRUCT ps;
  587.  
  588.             hdc = BeginPaint(hwnd, &ps);
  589.  
  590.             DrawBoundingBox(hwnd, hdc, 4201);
  591.  
  592.             EndPaint(hwnd, &ps);
  593.             return (TRUE);
  594.         }
  595.  
  596.         case WM_COMMAND: {
  597.             int i, n;
  598.             UNIT far *up;
  599.             HCURSOR hCursor;
  600.             HWND ChildHwnd;
  601.  
  602.  
  603.             switch (wParam) {
  604.                 case 4201:          /* Japanese Edit Control */
  605.                     if (HIWORD(lParam) == EN_CHANGE) {
  606.                         if (SendMessage(LOWORD(lParam), EM_LINELENGTH, 0, 0L) > 0) {
  607.                             EnableWindow(GetDlgItem(hwnd, 4211), TRUE);
  608.                         } else {
  609.                             EnableWindow(GetDlgItem(hwnd, 4211), FALSE);
  610.                         }
  611.                     }
  612.                     return (TRUE);
  613.  
  614.                 case 4211:          /* Search Button */
  615.                 case IDOK:
  616.                     up = (UNIT far *) SendDlgItemMessage(hwnd, 4201, EM_GETLINE, 0, 0L);
  617.                     i = unitlen(up);
  618.  
  619.                     if (!ISKANJI(up[0].kanji) && i <= 2) {
  620.                         /* Cannot search for less than 3 letters */
  621.                         MessageBeep(0);
  622.                     } else if (ISKANJI(up[0].kanji) && i <= 1 &&
  623.                                (HIBYTE(up[0].kanji) == 0x24 || HIBYTE(up[0].kanji) == 0x25)) {
  624.  
  625.                         /* Cannot search for less than 2 kana */
  626.                         MessageBeep(0);
  627.                     } else if (i > 0) {
  628.                         hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  629.                         ShowCursor(TRUE);
  630.                         EnableWindow(GetDlgItem(hwnd, 4212), FALSE);
  631.  
  632.                         SetDlgItemText(hwnd, 4202, "");
  633.                         n = SearchDictionary(hwnd, GetDlgItem(hwnd, 4201), GetDlgItem(hwnd, 4221));
  634.                         if (n <= 0) {
  635.                             MessageBeep(0);
  636.                             SetDlgItemText(hwnd, 4202, "No matches");
  637.                         } else {
  638.                             SetFocus(GetDlgItem(hwnd, 4221));
  639.                         }
  640.  
  641.                         ShowCursor(FALSE);
  642.                         SetCursor(hCursor);
  643.                     } else {
  644.                         MessageBeep(0);
  645.                     }
  646.                     return (TRUE);
  647.  
  648.                 case 4212: {        /* Insert Button */
  649.                     KANJI buf[MAXLINELEN], far *kp;
  650.                     LONG offset;
  651.                     FILEOPTIONS *f;
  652.  
  653.                     ChildHwnd = GetDlgItem(hwnd, 4221);
  654.  
  655.                     if (HIWORD(lParam) == BN_CLICKED && global.active != NULL) {
  656.                         n = SendMessage(ChildHwnd, LB_GETCURSEL, 0, 0L);
  657.                         if (n == LB_ERR) {
  658.                             EnableWindow(LOWORD(lParam), FALSE);
  659.                             return (TRUE);
  660.                         }
  661.  
  662.                         f = global.active;
  663.                         offset = SendMessage(ChildHwnd, LB_GETITEMDATA, n, 0L);
  664.                         kp = ConvertOffset(0, offset, buf);
  665.  
  666.                         /* Trim surrounding spaces */
  667.                         for (i = kanjilen(kp); i > 0; i--) {
  668.                             if (ISKANJI(kp[i])) {
  669.                                 if (kp[i] > 0x2121) break;
  670.                             } else {
  671.                                 if (kp[i] > ' ') break;
  672.                             }
  673.                         }
  674.  
  675.                         kp[i+1] = 0;
  676.  
  677.                         for (i = 0; kp[i]; i++) {
  678.                             if (ISKANJI(kp[i])) {
  679.                                 if (kp[i] > 0x2121) break;
  680.                             } else {
  681.                                 if (kp[i] > ' ') break;
  682.                             }
  683.                         }
  684.  
  685.                         if (kp[i] > 0) {
  686.                             TurnOffSelection(f);
  687.                             UndoAddTyping(f, f->current, kanjilen(kp + i), FALSE);
  688.                             InsertString(f, f->current, kp + i,
  689.                                 OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND);
  690.                         } else {
  691.                             MessageBeep(0);
  692.                             return (TRUE);
  693.                         }
  694.                     }
  695.  
  696.                     for (i = 0; i < NRCACHE; i++) {
  697.                         if (cache[i].string != NULL) FreeBlock(cache[i].string);
  698.                         cache[i].string = NULL;
  699.                     }
  700.  
  701.                     EndDialog(hwnd, TRUE);
  702.                     return (TRUE);
  703.                 }
  704.  
  705.                 case 4221:          /* Japanese List Box */
  706.                     ChildHwnd = GetDlgItem(hwnd, 4212);
  707.  
  708.                     if (HIWORD(lParam) == LBN_SELCHANGE || HIWORD(lParam) == LBN_DBLCLK) {
  709.                         n = SendMessage(LOWORD(lParam), LB_GETCURSEL, 0, 0L);
  710.                         if (n == LB_ERR) {
  711.                             EnableWindow(ChildHwnd, FALSE);
  712.                             return (TRUE);
  713.                         }
  714.  
  715.                         if (global.active != NULL) EnableWindow(ChildHwnd, TRUE);
  716.                         if (HIWORD(lParam) == LBN_DBLCLK) {
  717.                             /* Flash button */
  718.                             SendMessage(ChildHwnd, BM_SETSTATE, 1, 0L);
  719.                             SendMessage(ChildHwnd, BM_SETSTATE, 0, 0L);
  720.                             SendMessage(hwnd, WM_COMMAND, 4212, MAKELONG(ChildHwnd, BN_CLICKED));
  721.                         }
  722.                     }
  723.                     return (TRUE);
  724.  
  725.                 case IDCANCEL:      /* Done Button */
  726.                     for (i = 0; i < NRCACHE; i++) {
  727.                         if (cache[i].string != NULL) FreeBlock(cache[i].string);
  728.                         cache[i].string = NULL;
  729.                     }
  730.                     EndDialog(hwnd, FALSE);
  731.                     return (TRUE);
  732.  
  733.                 default:
  734.                     break;
  735.             }
  736.             break;
  737.         }
  738.  
  739.         case WM_COMPAREITEM:
  740.         case WM_DELETEITEM:
  741.         case WM_DRAWITEM:
  742.         case WM_MEASUREITEM:
  743.             return (JlistProc(hwnd, message, wParam, lParam, TRUE, ConvertOffset));
  744.     }
  745.  
  746.     return (FALSE);
  747. }
  748.