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

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3. #include "jwp.h"
  4.  
  5. #include "idm.h"
  6.  
  7.  
  8. typedef struct {
  9.     KANJI far *shortcut;
  10.     KANJI far *phrase;
  11.     BOOL dynamic;
  12.     BOOL hidden;
  13. } GLOSSARY;
  14.  
  15.  
  16. static GLOSSARY Glossary[MAXGLOSSARY];
  17.  
  18. static int NrGlossary = 0;
  19. static BOOL GlossaryChanged = FALSE;
  20. static BOOL sizing = FALSE;
  21.  
  22. static KANJI far *CurrentShortCut;
  23. static KANJI far *CurrentPhrase;
  24.  
  25.  
  26.  
  27. static KANJI far *ConvertGlossary (int id, LONG lParam, KANJI *buf)
  28. {
  29.     return (Glossary[lParam].shortcut);
  30. }
  31.  
  32.  
  33.  
  34. static KANJI far *ConvertGlossary1 (int id, LONG lParam, KANJI *buf)
  35. {
  36.     return (Glossary[lParam].phrase);
  37. }
  38.  
  39.  
  40.  
  41. static int GlossaryComp (void const *v1, void const *v2)
  42. {
  43.     GLOSSARY *p1, *p2;
  44.  
  45.     p1 = (GLOSSARY *) v1;
  46.     p2 = (GLOSSARY *) v2;
  47.  
  48.     return (kanjicmp(p1->shortcut, p2->shortcut));
  49. }
  50.  
  51.  
  52.  
  53. void ReadGlossary (char *filename)
  54. {
  55.     int i, j, len, fd;
  56.     OFSTRUCT of;
  57.  
  58.     /* Clear the old glossary */
  59.  
  60.     for (i = 0; i < NrGlossary; i++) {
  61.         if (Glossary[i].shortcut != NULL) FreeBlock(Glossary[i].shortcut);
  62.         if (Glossary[i].phrase != NULL) FreeBlock(Glossary[i].phrase);
  63.         Glossary[i].shortcut = Glossary[i].phrase = NULL;
  64.     }
  65.  
  66.     fd = OpenFile(filename, &of, OF_READ);
  67.     if (fd < 0) return;
  68.  
  69.     /* Read the glossary file */
  70.  
  71.     lseek(fd, 0L, 0);
  72.     read(fd, &NrGlossary, sizeof(int));
  73.  
  74.     for (i = 0; i < NrGlossary; i++) {
  75.         /* Read the options */
  76.         read(fd, &j, sizeof(int));
  77.         Glossary[i].dynamic = j & 0x0001;
  78.         Glossary[i].hidden = j & 0x0002;
  79.  
  80.         /* Read the short-cut */
  81.         read(fd, &len, sizeof(int));
  82.         len *= sizeof(KANJI);
  83.         Glossary[i].shortcut = BlockAlloc(len);
  84.         if (Glossary[i].shortcut == NULL) break;
  85.         _lread(fd, (char far *) Glossary[i].shortcut, len);
  86.  
  87.         /* Read the phrase */
  88.         read(fd, &len, sizeof(int));
  89.         len *= sizeof(KANJI);
  90.         Glossary[i].phrase = BlockAlloc(len);
  91.         if (Glossary[i].shortcut == NULL) break;
  92.         _lread(fd, (char far *) Glossary[i].phrase, len);
  93.     }
  94.  
  95.     close(fd);
  96.  
  97.     if (NrGlossary > 0) {
  98.         qsort(Glossary, NrGlossary, sizeof(GLOSSARY), GlossaryComp);
  99.     }
  100. }
  101.  
  102.  
  103.  
  104. void WriteGlossary (char *filename)
  105. {
  106.     int i, j, len, fd;
  107.     OFSTRUCT of;
  108.  
  109.  
  110.     if (!GlossaryChanged) return;
  111.  
  112.     fd = OpenFile(filename, &of, OF_WRITE | OF_CREATE);
  113.     if (fd < 0) {
  114.         ErrorMessage(global.hwnd, "Cannot create glossary file %s!", filename);
  115.         return;
  116.     }
  117.  
  118.     for (i = j = 0; i < NrGlossary; i++) {
  119.         if (Glossary[i].shortcut != NULL) j++;
  120.     }
  121.  
  122.     lseek(fd, 0L, 0);
  123.     write(fd, &j, sizeof(int));
  124.  
  125.     for (i = 0; i < NrGlossary; i++) {
  126.         if (Glossary[i].shortcut == NULL) continue;
  127.  
  128.         /* Write the options flag */
  129.         j = 0;
  130.         if (Glossary[i].dynamic) j |= 0x0001;
  131.         if (Glossary[i].hidden) j |= 0x0002;
  132.         write(fd, &j, sizeof(int));
  133.  
  134.         /* Write the short-cut */
  135.         len = kanjilen(Glossary[i].shortcut) + 1;
  136.         write(fd, &len, sizeof(int));
  137.         len *= sizeof(KANJI);
  138.         _lwrite(fd, (char far *) Glossary[i].shortcut, len);
  139.  
  140.         /* Write the phrase */
  141.         len = kanjilen(Glossary[i].phrase) + 1;
  142.         write(fd, &len, sizeof(int));
  143.         len *= sizeof(KANJI);
  144.         _lwrite(fd, (char far *) Glossary[i].phrase, len);
  145.     }
  146.  
  147.     close(fd);
  148. }
  149.  
  150.  
  151.  
  152. int SearchGlossary (KANJI far *key)
  153. {
  154.     int len;
  155.     int top, bottom, middle;
  156.     int diff;
  157.  
  158.  
  159.     if (NrGlossary <= 0) return (-2);
  160.  
  161.  
  162.     /* Now binary search */
  163.  
  164.     top = 0;
  165.     bottom = NrGlossary - 1;
  166.  
  167.     len = kanjilen(key);
  168.  
  169.     if (!kanjicmp(key, Glossary[top].shortcut)) {
  170.         if (Glossary[top].dynamic) return (top);
  171.     } else if (!kanjincmp(key, Glossary[top].shortcut, len)) {
  172.         if (Glossary[top].dynamic) return (-1);
  173.     }
  174.  
  175.     if (!kanjicmp(key, Glossary[bottom].shortcut)) {
  176.         return (Glossary[bottom].dynamic ? bottom : -2);
  177.     } else if (!kanjincmp(key, Glossary[bottom].shortcut, len)) {
  178.         return (Glossary[bottom].dynamic ? -1 : -2);
  179.     }
  180.  
  181.  
  182.     for (;;) {
  183.         middle = (top + bottom) / 2;
  184.  
  185.         diff = kanjicmp(key, Glossary[middle].shortcut);
  186.  
  187.         if (diff == 0) {
  188.             return (Glossary[middle].dynamic ? middle : -2);
  189.         }
  190.  
  191.         if (top >= bottom - 1) {
  192.             for (; bottom < NrGlossary; bottom++) {
  193.                 diff = kanjincmp(key, Glossary[bottom].shortcut, len);
  194.                 if (!Glossary[bottom].dynamic || diff != 0) continue;
  195.                 return (-1);
  196.             }
  197.             return (-2);
  198.         }
  199.  
  200.         if (diff > 0) top = middle;
  201.         else bottom = middle;
  202.     }
  203. }
  204.  
  205.  
  206.  
  207. KANJI far *GetGlossary (int index)
  208. {
  209.     return (Glossary[index].phrase);
  210. }
  211.  
  212.  
  213.  
  214.  
  215. BOOL FAR PASCAL EditGlossaryProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  216. {
  217.     switch (message) {
  218.         case WM_INITDIALOG: {
  219.             int i;
  220.             FILEOPTIONS *f;
  221.             KANJI buf[BUFSIZE];
  222.  
  223.             /* Set the type and mode-change icon */
  224.             SendDlgItemMessage(hwnd, 4201, EM_SETMODIFY, FN_CONTROL | FN_NOKANJI, 0L);
  225.             SendDlgItemMessage(hwnd, 4201, EM_SETRECT, GetDlgItem(hwnd, 4211), 0L);
  226.  
  227.             SendDlgItemMessage(hwnd, 4202, EM_SETMODIFY, FN_CONTROL, 0L);
  228.             SendDlgItemMessage(hwnd, 4202, EM_SETRECT, GetDlgItem(hwnd, 4211), 0L);
  229.  
  230.             f = (FILEOPTIONS *) SendDlgItemMessage(hwnd, 4201, EM_GETHANDLE, 0, 0L);
  231.             SendDlgItemMessage(hwnd, 4211, EM_SETHANDLE, f->hwnd, 0L);  /* mode-change icon */
  232.  
  233.             if (CurrentShortCut != NULL) {
  234.                 SendDlgItemMessage(hwnd, 4201, EM_REPLACESEL, 0, (LONG) CurrentShortCut);
  235.                 SetFocus(GetDlgItem(hwnd, 4202));
  236.             }
  237.  
  238.             if (CurrentPhrase != NULL) {
  239.                 /* Edit */
  240.                 SendDlgItemMessage(hwnd, 4202, EM_REPLACESEL, 0, (LONG) CurrentPhrase);
  241.                 i = kanjilen(CurrentPhrase);
  242.                 SendDlgItemMessage(hwnd, 4202, EM_SETSEL, i, MAKELONG(0, i-1));
  243.                 SetWindowText(GetDlgItem(hwnd, 1), "&Done!");
  244.                 SetWindowText(hwnd, "Edit an Existing Glossary Item");
  245.             } else {
  246.                 /* Add */
  247.                 SetWindowText(GetDlgItem(hwnd, 1), "&Add!");
  248.                 SetWindowText(hwnd, "Add a Glossary Item");
  249.             }
  250.  
  251.             CenterDialogBox(hwnd);
  252.             return (TRUE);
  253.         }
  254.  
  255.         case WM_COMMAND:
  256.             switch (wParam) {
  257.                 case IDCANCEL:
  258.                     CurrentShortCut = CurrentPhrase = NULL;
  259.                     EndDialog(hwnd, FALSE);
  260.                     return (TRUE);
  261.  
  262.                 case IDOK: {
  263.                     int i;
  264.                     UNIT far *up, far *up1;
  265.                     KANJI ch;
  266.  
  267.                     up1 = (UNIT far *) SendDlgItemMessage(hwnd, 4202, EM_GETLINE, 0, 0L);
  268.                     if (unitlen(up1) <= 0) {
  269.                         ErrorMessage(hwnd, "Sorry, you must enter a phrase for the short-cut.");
  270.                         SetFocus(GetDlgItem(hwnd, 4202));
  271.                         return (TRUE);
  272.                     }
  273.  
  274.                     up = (UNIT far *) SendDlgItemMessage(hwnd, 4201, EM_GETLINE, 0, 0L);
  275.                     if (unitlen(up) <= 0) {
  276.                         ErrorMessage(hwnd, "Sorry, you must enter a short-cut for the phrase.");
  277.                         SetFocus(GetDlgItem(hwnd, 4201));
  278.                         return (TRUE);
  279.                     }
  280.  
  281.                     CurrentShortCut = (KANJI far *) BlockAlloc((unitlen(up) + 5) * sizeof(KANJI));
  282.                     for (i = 0; up[i].kanji; i++) CurrentShortCut[i] = up[i].kanji;
  283.                     CurrentShortCut[i] = 0;
  284.  
  285.                     CurrentPhrase = (KANJI far *) BlockAlloc((unitlen(up1) + 5) * sizeof(KANJI));
  286.                     for (i = 0; up1[i].kanji; i++) CurrentPhrase[i] = up1[i].kanji;
  287.                     CurrentPhrase[i] = 0;
  288.  
  289.                     EndDialog(hwnd, TRUE);
  290.                     return (TRUE);
  291.                 }
  292.             }
  293.             return (TRUE);
  294.  
  295.         case WM_PAINT: {
  296.             HDC hdc;
  297.             PAINTSTRUCT ps;
  298.  
  299.             hdc = BeginPaint(hwnd, &ps);
  300.  
  301.             DrawBoundingBox(hwnd, hdc, 4201);
  302.             DrawBoundingBox(hwnd, hdc, 4202);
  303.  
  304.             EndPaint(hwnd, &ps);
  305.             return (TRUE);
  306.         }
  307.     }
  308.     return (FALSE);
  309. }
  310.  
  311.  
  312.  
  313. BOOL FAR PASCAL GlossaryProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  314. {
  315.     switch (message) {
  316.         case WM_INITDIALOG: {
  317.             int i;
  318.  
  319.             for (i = 0; i < NrGlossary; i++) {
  320.                 SendDlgItemMessage(hwnd, 4211, LB_ADDSTRING, 0, (LONG) i);
  321.             }
  322.  
  323.             if (NrGlossary > 0) {
  324.                 SendDlgItemMessage(hwnd, 4211, LB_SETCURSEL, 0, 0L);
  325.                 i = SendDlgItemMessage(hwnd, 4211, LB_GETITEMDATA, 0, 0L);
  326.                 SendDlgItemMessage(hwnd, 4201, EM_REPLACESEL, 0, (LONG) Glossary[i].shortcut);
  327.                 SendDlgItemMessage(hwnd, 4202, EM_REPLACESEL, 0, (LONG) Glossary[i].phrase);
  328.                 CheckDlgButton (hwnd, 4231, Glossary[0].dynamic);
  329.                 CheckDlgButton (hwnd, 4232, Glossary[0].hidden);
  330.             } else {
  331.                 EnableWindow(GetDlgItem(hwnd, 4231), FALSE);
  332.                 EnableWindow(GetDlgItem(hwnd, 4232), FALSE);
  333.             }
  334.  
  335.             SetFocus(GetDlgItem(hwnd, 4211));
  336.  
  337.             CenterDialogBox(hwnd);
  338.             return (TRUE);
  339.         }
  340.  
  341.         case WM_KEYDOWN:
  342.             switch (wParam) {
  343.                 case VK_ESCAPE: SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  344.                                 return (TRUE);
  345.             }
  346.             break;
  347.  
  348.         case WM_COMMAND: {
  349.             int i, j;
  350.  
  351.             switch (wParam) {
  352.                 case 4211:      /* List Box */
  353.                     switch (HIWORD(lParam)) {
  354.                         case LBN_SELCHANGE:
  355.                             i = SendDlgItemMessage(hwnd, 4211, LB_GETCURSEL, 0, 0L);
  356.                             if (NrGlossary <= 0 || i == LB_ERR) {
  357.                                 SendDlgItemMessage(hwnd, 4201, EM_REPLACESEL, 0, (LONG) NULL);
  358.                                 SendDlgItemMessage(hwnd, 4202, EM_REPLACESEL, 0, (LONG) NULL);
  359.                                 EnableWindow(GetDlgItem(hwnd, 4231), FALSE);
  360.                                 EnableWindow(GetDlgItem(hwnd, 4232), FALSE);
  361.                                 return (TRUE);
  362.                             }
  363.  
  364.                             i = SendDlgItemMessage(hwnd, 4211, LB_GETITEMDATA, i, 0L);
  365.  
  366.                             SendDlgItemMessage(hwnd, 4201, EM_REPLACESEL, 0, (LONG) Glossary[i].shortcut);
  367.                             SendDlgItemMessage(hwnd, 4202, EM_REPLACESEL, 0, (LONG) Glossary[i].phrase);
  368.                             CheckDlgButton (hwnd, 4231, Glossary[i].dynamic);
  369.                             CheckDlgButton (hwnd, 4232, Glossary[i].hidden);
  370.                             EnableWindow(GetDlgItem(hwnd, 4231), TRUE);
  371.                             EnableWindow(GetDlgItem(hwnd, 4232), TRUE);
  372.                             InvalidateRect(GetDlgItem(hwnd, 4201), NULL, TRUE);
  373.                             InvalidateRect(GetDlgItem(hwnd, 4202), NULL, TRUE);
  374.                             return (TRUE);
  375.  
  376.                         case LBN_DBLCLK:
  377.                             SendMessage(hwnd, WM_COMMAND, 4222, 0L);    /* Edit */
  378.                             return (TRUE);
  379.                     }
  380.                     return (TRUE);
  381.  
  382.                 case 4221: {    /* Add */
  383.                     int len;
  384.  
  385.                     CurrentShortCut = CurrentPhrase = NULL;
  386.                     if (!DialogBox(hInstance, "EditGlossary", hwnd, EditGlossaryProc)) {
  387.                         CurrentShortCut = CurrentPhrase = NULL;
  388.                         return (TRUE);
  389.                     }
  390.  
  391.                     /* Trim trailing blanks */
  392.  
  393.                     len = kanjilen(CurrentShortCut);
  394.  
  395.                     for (i = len - 1; i >= 0; i--) {
  396.                         CurrentShortCut[i] &= 0x7f7f;
  397.                         if (CurrentShortCut[i] != 0x2121 && CurrentShortCut[i] > ' ') break;
  398.                     }
  399.  
  400.                     CurrentShortCut[i+1] = 0;
  401.  
  402.                     /* Duplicate? */
  403.  
  404.                     for (i = 0; i < NrGlossary; i++) {
  405.                         if (Glossary[i].shortcut == NULL) continue;
  406.                         if (!kanjicmp(CurrentShortCut, Glossary[i].shortcut)) break;
  407.                     }
  408.  
  409.                     if (i < NrGlossary) {
  410.                         if (YesNo(hwnd, "The short-cut you want to add already exists.  "
  411.                                         "You should first delete the old glossary item before "
  412.                                         "adding a new one with the same short-cut.\n\n"
  413.                                         "Do you REALLY want to overwrite the already-existing "
  414.                                         "short-cut?") != IDYES) {
  415.  
  416.                             FreeBlock(CurrentShortCut);
  417.                             FreeBlock(CurrentPhrase);
  418.                             CurrentShortCut = CurrentPhrase = NULL;
  419.                             return (TRUE);
  420.                         }
  421.  
  422.                         FreeBlock((void far *) CurrentShortCut);
  423.                         /* Replace the phrase */
  424.                         len = kanjilen(CurrentPhrase);
  425.                         FreeBlock((void far *) Glossary[i].phrase);
  426.                         Glossary[i].phrase = CurrentPhrase;
  427.                         InvalidateRect(GetDlgItem(hwnd, 4221), NULL, TRUE);
  428.                     } else {
  429.                         /* Put it in the glossary */
  430.  
  431.                         Glossary[NrGlossary].shortcut = CurrentShortCut;
  432.                         Glossary[NrGlossary].phrase = CurrentPhrase;
  433.  
  434.                         Glossary[NrGlossary].dynamic = TRUE;
  435.                         Glossary[NrGlossary].hidden = FALSE;
  436.  
  437.                         SendDlgItemMessage(hwnd, 4211, LB_ADDSTRING, 0, (LONG) NrGlossary);
  438.  
  439.                         i = NrGlossary++;
  440.                     }
  441.  
  442.                     /* Which item is the one just added? */
  443.  
  444.                     len = SendDlgItemMessage(hwnd, 4211, LB_GETCOUNT, 0, 0L);
  445.  
  446.                     for (j = 0; j < len; j++) {
  447.                         if (SendDlgItemMessage(hwnd, 4211, LB_GETITEMDATA, j, 0L) == i) break;
  448.                     }
  449.  
  450.                     if (j < len) SendDlgItemMessage(hwnd, 4211, LB_SETCURSEL, j, 0L);
  451.  
  452.                     SendMessage(hwnd, WM_COMMAND, 4211, MAKELONG(hwnd, LBN_SELCHANGE));
  453.  
  454.                     GlossaryChanged = TRUE;
  455.  
  456.                     CurrentPhrase = CurrentShortCut = NULL;
  457.  
  458.                     SetFocus(GetDlgItem(hwnd, 4211));
  459.                     return (TRUE);
  460.                 }
  461.  
  462.                 case 4222: {    /* Edit */
  463.                     int len;
  464.  
  465.                     i = SendDlgItemMessage(hwnd, 4211, LB_GETCURSEL, 0, 0L);
  466.                     if (i == LB_ERR) {
  467.                         MessageBeep(0);
  468.                         return (TRUE);
  469.                     }
  470.  
  471.                     i = SendDlgItemMessage(hwnd, 4211, LB_GETITEMDATA, i, 0L);
  472.  
  473.                     CurrentShortCut = Glossary[i].shortcut;
  474.                     CurrentPhrase = Glossary[i].phrase;
  475.  
  476.                     if (!DialogBox(hInstance, "EditGlossary", hwnd, EditGlossaryProc)) {
  477.                         CurrentShortCut = CurrentPhrase = NULL;
  478.                         return (TRUE);
  479.                     }
  480.  
  481.                     /* Trim trailing blanks */
  482.  
  483.                     len = kanjilen(CurrentShortCut);
  484.  
  485.                     for (j = len - 1; j >= 0; j--) {
  486.                         CurrentShortCut[j] &= 0x7f7f;
  487.                         if (CurrentShortCut[j] != 0x2121 && CurrentShortCut[j] > ' ') break;
  488.                     }
  489.  
  490.                     CurrentShortCut[j+1] = 0;
  491.  
  492.                     if (!kanjicmp(CurrentShortCut, Glossary[i].shortcut)) {
  493.                         FreeBlock(CurrentShortCut);
  494.                         FreeBlock(CurrentPhrase);
  495.                         CurrentShortCut = CurrentPhrase = NULL;
  496.                         return (TRUE);
  497.                     }
  498.  
  499.                     FreeBlock(Glossary[i].shortcut);
  500.                     Glossary[i].shortcut = CurrentShortCut;
  501.                     FreeBlock(Glossary[i].phrase);
  502.                     Glossary[i].phrase = CurrentPhrase;
  503.  
  504.                     CurrentShortCut = CurrentPhrase = NULL;
  505.                     return (TRUE);
  506.                 }
  507.  
  508.                 case 4223:      /* Delete */
  509.                     if (NrGlossary <= 0) return (TRUE);
  510.                     i = SendDlgItemMessage(hwnd, 4211, LB_GETCURSEL, 0, 0L);
  511.                     if (i == LB_ERR) return (TRUE);
  512.  
  513.                     if (YesNo(hwnd, "Do you REALLY want to delete this item?") != IDYES)
  514.                         return (TRUE);
  515.  
  516.                     j = SendDlgItemMessage(hwnd, 4211, LB_GETITEMDATA, i, 0L);
  517.  
  518.                     SendDlgItemMessage(hwnd, 4211, LB_DELETESTRING, i, 0L);
  519.  
  520.                     FreeBlock(Glossary[j].shortcut);
  521.                     FreeBlock(Glossary[j].phrase);
  522.  
  523.                     Glossary[j].shortcut = Glossary[j].phrase = NULL;
  524.  
  525.                     if (SendDlgItemMessage(hwnd, 4211, LB_GETCOUNT, 0, 0L) > 0) {
  526.                         SendDlgItemMessage(hwnd, 4211, LB_SETCURSEL, 0, 0L);
  527.                     }
  528.                     SendMessage(hwnd, WM_COMMAND, 4211, MAKELONG(hwnd, LBN_SELCHANGE));
  529.                     GlossaryChanged = TRUE;
  530.  
  531.                     SetFocus(GetDlgItem(hwnd, 4211));
  532.                     return (TRUE);
  533.  
  534.                 case 4231:      /* Dynamic button */
  535.                     i = SendDlgItemMessage(hwnd, 4211, LB_GETCURSEL, 0, 0L);
  536.                     if (i == LB_ERR) return (TRUE);
  537.  
  538.                     j = SendDlgItemMessage(hwnd, 4211, LB_GETITEMDATA, i, 0L);
  539.                     Glossary[j].dynamic = IsDlgButtonChecked(hwnd, 4231);
  540.                     GlossaryChanged = TRUE;
  541.                     return (TRUE);
  542.  
  543.                 case 4232:      /* Hidden button */
  544.                     i = SendDlgItemMessage(hwnd, 4211, LB_GETCURSEL, 0, 0L);
  545.                     if (i == LB_ERR) return (TRUE);
  546.  
  547.                     j = SendDlgItemMessage(hwnd, 4211, LB_GETITEMDATA, i, 0L);
  548.                     Glossary[j].hidden = IsDlgButtonChecked(hwnd, 4232);
  549.                     GlossaryChanged = TRUE;
  550.                     return (TRUE);
  551.  
  552.                 case IDOK:
  553.                     /* Compact the entries */
  554.  
  555.                     for (i = 0; i < NrGlossary; i++) {
  556.                         if (Glossary[i].shortcut == NULL) {
  557.                             for (j = i + 1; j < NrGlossary; j++)
  558.                                 Glossary[j-1] = Glossary[j];
  559.  
  560.                             NrGlossary--;
  561.                             i--;
  562.                         }
  563.                     }
  564.  
  565.                     if (NrGlossary > 0) {
  566.                         qsort(Glossary, NrGlossary, sizeof(GLOSSARY), GlossaryComp);
  567.                     }
  568.  
  569.                     if (global.glisthwnd != NULL)
  570.                         SendMessage(global.glisthwnd, WM_USER, 0, 0L);
  571.  
  572.                     EndDialog(hwnd, FALSE);
  573.                     return (TRUE);
  574.             }
  575.  
  576.             return (FALSE);
  577.         }
  578.  
  579.         case WM_COMPAREITEM:
  580.         case WM_DELETEITEM:
  581.         case WM_DRAWITEM:
  582.         case WM_MEASUREITEM:
  583.             return (JlistProc(hwnd, message, wParam, lParam, TRUE, ConvertGlossary));
  584.     }
  585.  
  586.     return (FALSE);
  587. }
  588.  
  589.  
  590.  
  591. BOOL FAR PASCAL GlossaryListProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  592. {
  593.     int i, j;
  594.  
  595.     switch (message) {
  596.         case WM_INITDIALOG: {
  597.             RECT rect;
  598.  
  599.             sizing = FALSE;
  600.  
  601.             GetWindowRect(global.hwnd, &rect);
  602.  
  603.             SetWindowPos(hwnd, NULL,
  604.                          rect.left + global.glistsize.left,
  605.                          rect.top + global.glistsize.top,
  606.                          0, 0, SWP_NOSIZE | SWP_NOZORDER);
  607.  
  608.             SetWindowPos(hwnd, NULL, 0, 0, global.glistsize.right, global.glistsize.bottom, SWP_NOMOVE | SWP_NOZORDER);
  609.  
  610.             SendMessage(hwnd, WM_USER, 0, 0L);
  611.  
  612.             return (TRUE);
  613.         }
  614.  
  615.         case WM_USER:
  616.             SendDlgItemMessage(hwnd, 4201, LB_RESETCONTENT, 0, 0L);
  617.             for (i = 0; i < NrGlossary; i++) {
  618.                 if (Glossary[i].hidden) continue;
  619.                 SendDlgItemMessage(hwnd, 4201, LB_ADDSTRING, 0, (LONG) i);
  620.             }
  621.             return (TRUE);
  622.  
  623.         case WM_MOVE: {
  624.             RECT rect1, rect2;
  625.  
  626.             GetWindowRect(global.hwnd, &rect1);
  627.             GetWindowRect(hwnd, &rect2);
  628.  
  629.             global.glistsize.left = rect2.left - rect1.left;
  630.             global.glistsize.top = rect2.top - rect1.top;
  631.             return (TRUE);
  632.         }
  633.  
  634.         case WM_SIZE: {
  635.             RECT rect1, rect2, rect3;
  636.  
  637.             if (sizing) return (TRUE);
  638.  
  639.             GetWindowRect(hwnd, &rect1);
  640.             GetClientRect(hwnd, &rect2);
  641.  
  642.             MoveWindow(GetDlgItem(hwnd, 4201), 0, 0, rect2.right, rect2.bottom, TRUE);
  643.             GetWindowRect(GetDlgItem(hwnd, 4201), &rect3);
  644.  
  645.             rect3.right += (rect1.right - rect1.left - rect2.right);
  646.             rect3.bottom += (rect1.bottom - rect1.top - rect2.bottom);
  647.  
  648.             sizing = TRUE;
  649.  
  650.             global.glistsize.right = i = rect3.right - rect3.left;
  651.             global.glistsize.bottom = j = rect3.bottom - rect3.top;
  652.  
  653.             SetWindowPos(hwnd, NULL, 0, 0, i, j, SWP_NOMOVE | SWP_NOZORDER);
  654.             sizing = FALSE;
  655.  
  656.             return (TRUE);
  657.         }
  658.  
  659.         case WM_SYSCOMMAND:
  660.             if ((wParam & 0xfff0) == SC_CLOSE) {
  661.                 SetActiveWindow(global.hwnd);
  662.  
  663.                 EndDialog(hwnd, FALSE);
  664.                 SendMessage(global.tbhwnd, BM_SETSTATE, FALSE, ID_GLOSSARY);
  665.                 CheckMenuItem(hmenu, IDM_VIEWGLOSSARY, MF_UNCHECKED | MF_BYCOMMAND);
  666.                 global.glisthwnd = NULL;
  667.                 return (TRUE);
  668.             }
  669.             break;
  670.  
  671.         case WM_COMMAND:
  672.             switch (wParam) {
  673.                 case 4201:
  674.                     switch (HIWORD(lParam)) {
  675.                         case LBN_SELCHANGE: {
  676.                             FILEOPTIONS *f;
  677.  
  678.                             i = SendDlgItemMessage(hwnd, 4201, LB_GETCURSEL, 0, 0L);
  679.                             if (i == LB_ERR) return (TRUE);
  680.                             if (global.active == NULL) {
  681.                                 MessageBeep(0);
  682.                                 SendDlgItemMessage(hwnd, 4201, LB_SETCURSEL, LB_ERR, 0L);
  683.                                 return (TRUE);
  684.                             }
  685.  
  686.                             i = SendDlgItemMessage(hwnd, 4201, LB_GETITEMDATA, i, 0L);
  687.  
  688.                             f = global.active;
  689.  
  690.                             TurnOffSelection(f);
  691.                             UndoAddTyping(f, f->current, kanjilen(Glossary[i].phrase), FALSE);
  692.                             InsertString(f, f->current, Glossary[i].phrase,
  693.                                 OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND);
  694.  
  695.                             SendDlgItemMessage(hwnd, 4201, LB_SETCURSEL, LB_ERR, 0L);
  696.                             SetActiveWindow(global.hwnd);
  697.  
  698.                             switch (global.glistbehaviour) {
  699.                                 case 0: break;
  700.                                 case 1: EndDialog(hwnd, FALSE);
  701.                                         CheckMenuItem(hmenu, IDM_VIEWGLOSSARY, MF_UNCHECKED | MF_BYCOMMAND);
  702.                                         global.glisthwnd = NULL;
  703.                                         SendMessage(global.tbhwnd, BM_SETSTATE, FALSE, ID_GLOSSARY);
  704.                                         break;
  705.                             }
  706.                             return (TRUE);
  707.                         }
  708.                     }
  709.                     return (TRUE);
  710.             }
  711.             return (FALSE);
  712.  
  713.         case WM_KEYDOWN:
  714.         case WM_CHAR:
  715.             switch (wParam) {
  716.                 case VK_ESCAPE: SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  717.                                 return (TRUE);
  718.             }
  719.             break;
  720.  
  721.         case WM_COMPAREITEM:
  722.         case WM_DELETEITEM:
  723.         case WM_DRAWITEM:
  724.         case WM_MEASUREITEM:
  725.             return (JlistProc(hwnd, message, wParam, lParam, TRUE, ConvertGlossary1));
  726.     }
  727.  
  728.     return (FALSE);
  729. }
  730.