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

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3. #include "jwp.h"
  4.  
  5.  
  6. #define STACKDEPTH      50
  7.  
  8. /*
  9. #define tolower(x)      AnsiLower ((LPSTR) (LONG) (BYTE) (x))
  10. #define toupper(x)      AnsiUpper ((LPSTR) (LONG) (BYTE) (x))
  11. */
  12. #define tolower(x)        (('A' <= (x) && (x) <= 'Z') ? (x) + 32 : (x))
  13. #define toupper(x)        (('a' <= (x) && (x) <= 'a') ? (x) - 32 : (x))
  14. #define islower(x)      ('a' <= (x) && (x) <= 'z')
  15. #define isupper(x)      ('A' <= (x) && (x) <= 'Z')
  16. #define isalpha(x)      (isupper(x) || islower(x))
  17.  
  18.  
  19. static char Typed[10] = "";
  20. static char Temp[10] = "";
  21. static KANJI InputBuffer[10];
  22. static KANJI KanjiBuffer[MAXLINELEN];
  23. static KANJI LastConv[MAXLINELEN];
  24. BYTE LastConvKey[256];
  25. static int LastLen;
  26.  
  27. static struct {
  28.     int offset;
  29.     int length;
  30. } GlossaryStack[STACKDEPTH];
  31. static int Stackp = 0;
  32.         
  33.  
  34. typedef struct {
  35.     int state;
  36.     char *input;
  37.     int next;
  38. } STATE;
  39.  
  40.  
  41. /* The State Machine */
  42.  
  43. static STATE states[] = {
  44.     { 0, "aiueo",    -1 },          /* Start */
  45.     { 0, "hmzbpr",    1 },
  46.     { 0, "kg",       30 },
  47.     { 0, "y",        27 },
  48.     { 0, "n",         3 },
  49.     { 0, "j",         4 },
  50.     { 0, "t",         5 },
  51.     { 0, "d",         6 },
  52.     { 0, "s",         7 },
  53.     { 0, "c",         8 },
  54.     { 0, "w",         9 },
  55.     { 0, "v",        13 },
  56.     { 0, "f",        14 },
  57.     { 0, "+",        24 },
  58.     { 0, "`",        -1 },
  59.     { 0, "'",        -1 },
  60.     { 0, "",         -1 },
  61.  
  62.     { 1, "aiueo",    -1 },          /* {khmgjdbpr} */
  63.     { 1, "y",         2 },
  64.  
  65.     { 2, "aueo",     -1 },          /* [...]y */
  66.  
  67.     { 3, "y",         2 },          /* n */
  68.     { 3, "aiueo'",   -1 },
  69.  
  70.     { 4, "y",         2 },          /* j */
  71.     { 4, "aiueo",    -1 },
  72.  
  73.     { 5, "y",         2 },          /* t */
  74.     { 5, "aiueo",    -1 },
  75.     { 5, "sz",       10 },
  76.     { 5, "c",        28 },
  77.  
  78.     { 6, "aiueo",    -1 },          /* d */
  79.     { 6, "y",        11 },
  80.  
  81.     { 7, "y",         2 },          /* s */
  82.     { 7, "aiueo",    -1 },
  83.     { 7, "h",        12 },
  84.  
  85.     { 8, "y",         2 },          /* c */
  86.     { 8, "h",        12 },
  87.     { 8, "i",        -1 },
  88.     { 8, "/",        -1 },
  89.  
  90.     { 9, "aieo",     -1 },          /* w */
  91.  
  92.     { 10, "u",       -1 },          /* t{sz} */
  93.  
  94.     { 11, "ui",      -1 },          /* dy */
  95.  
  96.     { 12, "aiueo",   -1 },          /* ch, sh */
  97.  
  98.     { 13, "aiueo",   -1 },          /* v */
  99.  
  100.     { 14, "aiueo",   -1 },          /* f */
  101.     { 14, "-",       -1 },
  102.  
  103.     { 22, "`",       -1 },          /* ` */
  104.  
  105.     { 23, "'",       -1 },          /* ' */
  106.  
  107.     { 24, "aiueo",   -1 },          /* + */
  108.     { 24, "t",       25 },
  109.     { 24, "y",        2 },
  110.     { 24, "w",       29 },
  111.  
  112.     { 25, "u",       -1 },          /* +t */
  113.     { 25, "sz",      26 },
  114.  
  115.     { 26, "u",       -1 },          /* +t{sz} */
  116.  
  117.     { 27, "aueo",    -1 },          /* y */
  118.     { 27, "=",       -1 },
  119.  
  120.     { 28, "y",        2 },          /* tc */
  121.     { 28, "h",       12 },
  122.     { 28, "i",       -1 },
  123.  
  124.     { 29, "a",       -1 },          /* +w */
  125.  
  126.     { 30, "aiueo",   -1 },          /* {kg}.. */
  127.     { 30, "y",        2 },
  128.     { 30, "w",       31 },
  129.  
  130.     { 31, "aieo",    -1 },          /* {kg}{uw}.. */
  131.  
  132.     { -999, NULL,    -1 }
  133. };
  134.  
  135.  
  136. /* The Conversion Tables */
  137.  
  138. static struct {
  139.     char ascii;
  140.     KANJI kanji;
  141. } JAsciiEquivalents[] = {
  142.     { ' ', 0x2121 },
  143.     { ',', 0x2122 },
  144.     { '.', 0x2123 },
  145.     { ',', 0x2124 },
  146.     { '.', 0x2125 },
  147.     { '.', 0x2126 },
  148.     { ':', 0x2127 },
  149.     { ';', 0x2128 },
  150.     { '?', 0x2129 },
  151.     { '!', 0x212a },
  152.     { '\"', 0x212b },
  153.     { '^', 0x2130 },
  154.     { '_', 0x2132 },
  155.     { '-', 0x213c },
  156.     { '-', 0x213d },
  157.     { '-', 0x213e },
  158.     { '/', 0x213f },
  159.     { '\\', 0x2140 },
  160.     { '~', 0x2141 },
  161.     { '|', 0x2143 },
  162.     { '`', 0x2146 },
  163.     { '\'', 0x2147 },
  164.     { '\"', 0x2148 },
  165.     { '\"', 0x2149 },
  166.     { '(', 0x214a },
  167.     { ')', 0x214b },
  168.     { '(', 0x214c },
  169.     { ')', 0x214d },
  170.     { '[', 0x214e },
  171.     { ']', 0x214f },
  172.     { '{', 0x2150 },
  173.     { '}', 0x2151 },
  174.     { '<', 0x2152 },
  175.     { '>', 0x2153 },
  176.     { '[', 0x215a },
  177.     { ']', 0x215b },
  178.     { '+', 0x215c },
  179.     { '-', 0x215d },
  180.     { 'x', 0x215f },
  181.     { '=', 0x2161 },
  182.     { '$', 0x2170 },
  183.     { '%', 0x2173 },
  184.     { '#', 0x2174 },
  185.     { '&', 0x2175 },
  186.     { '*', 0x2176 },
  187.     { '@', 0x2177 },
  188.     { '*', 0x2179 },
  189.     { '*', 0x217a },
  190.     { '*', 0x2228 },
  191.     { '=', 0x222e },
  192.     { '0', 0x2330 },
  193.     { '1', 0x2331 },
  194.     { '2', 0x2332 },
  195.     { '3', 0x2333 },
  196.     { '4', 0x2334 },
  197.     { '5', 0x2335 },
  198.     { '6', 0x2336 },
  199.     { '7', 0x2337 },
  200.     { '8', 0x2338 },
  201.     { '9', 0x2339 },
  202.     { '\0', 0x0000 }
  203. };
  204.  
  205. static struct {
  206.     char *string;
  207.     BYTE *real;
  208. } ComposedEquivalents[] = {
  209.     { "sha",  "\x37\x63" },
  210.     { "shi",  "\x37" },
  211.     { "shu",  "\x37\x65" },
  212.     { "she",  "\x37\x27" },
  213.     { "sho",  "\x37\x67" },
  214.  
  215.     { "ja",   "\x38\x63" },
  216.     { "ji",   "\x38" },
  217.     { "ju",   "\x38\x65" },
  218.     { "je",   "\x38\x27" },
  219.     { "jo",   "\x38\x67" },
  220.  
  221.     { "chi",  "\x41" },
  222.     { "ci",   "\x41" },
  223.  
  224.     { "cha",  "\x41\x63" },
  225.     { "chu",  "\x41\x65" },
  226.     { "che",  "\x41\x27" },
  227.     { "cho",  "\x41\x67" },
  228.  
  229.     { "tcha", "\x43\x41\x63" },
  230.     { "tchi", "\x43\x41" },
  231.     { "tci",  "\x43\x41" },
  232.     { "tchu", "\x43\x41\x65" },
  233.     { "tche", "\x43\x41\x27" },
  234.     { "tcho", "\x43\x41\x67" },
  235.  
  236.     { "tsu",  "\x44" },
  237.     { "tzu",  "\x44" },
  238.  
  239.     { "+tsu", "\x43" },
  240.     { "+tzu", "\x43" },
  241.  
  242.     { "dyi",  "\x47\x23" },
  243.     { "dyu",  "\x49\x25" },
  244.  
  245.     { "fa",   "\x55\x21" },
  246.     { "fi",   "\x55\x23" },
  247.     { "fu",   "\x55" },
  248.     { "fe",   "\x55\x27" },
  249.     { "fo",   "\x55\x29" },
  250.  
  251.     { "ye",   "\x24\x27" },
  252.  
  253.     { "kwa",  "\x2f\x21" },
  254.     { "kwi",  "\x2f\x23" },
  255.     { "kwe",  "\x2f\x27" },
  256.     { "kwo",  "\x2f\x29" },
  257.  
  258.     { "kua",  "\x2f\x21" },
  259.     { "kui",  "\x2f\x23" },
  260.     { "kue",  "\x2f\x27" },
  261.     { "kuo",  "\x2f\x29" },
  262.  
  263.     { "gwa",  "\x2f\x21" },
  264.     { "gwi",  "\x2f\x23" },
  265.     { "gwe",  "\x2f\x27" },
  266.     { "gwo",  "\x2f\x29" },
  267.  
  268.     { "gua",  "\x2f\x21" },
  269.     { "gui",  "\x2f\x23" },
  270.     { "gue",  "\x2f\x27" },
  271.     { "guo",  "\x2f\x29" },
  272.  
  273.     { "n'",   "\x73" },
  274.  
  275.     { "va",   "[\x25\x74\x25\x21]" },
  276.     { "vi",   "[\x25\x74\x25\x23]" },
  277.     { "vu",   "[\x25\x74]" },
  278.     { "ve",   "[\x25\x74\x25\x27]" },
  279.     { "vo",   "[\x25\x74\x25\x29]" },
  280.  
  281.     { "`",   "[\x21\x56]" },    /* These two are necessary because they */
  282.     { "'",   "[\x21\x57]" },    /* translate to non-ASCII equivalents   */
  283.  
  284.     { "y=",  "[\x21\x6f]" },    /* These two start with a letter */
  285.     { "f-",  "[\x21\x72]" },
  286.  
  287.     { NULL,  NULL }
  288. };
  289.  
  290. static char *direct[] = {
  291.     "+a", "a", "+i", "i", "+u", "u", "+e", "e", "+o", "o",
  292.     "ka", "ga", "ki", "gi", "ku", "gu", "ke", "ge", "ko", "go",
  293.     "sa", "za", "si", "zi", "su", "zu", "se", "ze", "so", "zo",
  294.     "ta", "da", "ti", "di", "+tu", "tu", "du", "te", "de", "to", "do",
  295.     "na", "ni", "nu", "ne", "no",
  296.     "ha", "ba", "pa", "hi", "bi", "pi", "hu", "bu", "pu", "he", "be", "pe",
  297.         "ho", "bo", "po",
  298.     "ma", "mi", "mu", "me", "mo",
  299.     "+ya", "ya", "+yu", "yu", "+yo", "yo",
  300.     "ra", "ri", "ru", "re", "ro",
  301.     "+wa", "wa", "wi", "we", "wo",
  302.     "n",
  303.     NULL
  304. };
  305.  
  306.  
  307.  
  308. BOOL ConvertOK (FILEOPTIONS *f)
  309. {
  310.     if (strlen(Typed) == 1 && strchr("AEIOU", Typed[0]) != NULL) return (TRUE);
  311.     if (SELPARA1(f) == NULL || SELPARA1(f) != SELPARA2(f)) return (FALSE);
  312.     return (TRUE);
  313. }
  314.  
  315.  
  316.  
  317. static int FindDirect (char *s)
  318. {
  319.     int i;
  320.  
  321.     for (i = 0; direct[i] != NULL; i++)
  322.         if (!strcmp(direct[i], s)) return (i);
  323.  
  324.     return (-1);
  325. }
  326.  
  327.  
  328. KANJI TranslateJAscii (KANJI ch, BOOL JtoA)
  329. {
  330.     int i;
  331.     char cch;
  332.  
  333.     if (JtoA) {
  334.         ch &= 0x7f7f;
  335.         for (i = 0; JAsciiEquivalents[i].ascii; i++) {
  336.             if (JAsciiEquivalents[i].kanji == ch) return (JAsciiEquivalents[i].ascii);
  337.         }
  338.         if (/* A */ 0x2341 <= ch && ch <= 0x235a /* Z */) return ('A' + (ch - 0x2341));
  339.         if (/* a */ 0x2361 <= ch && ch <= 0x237a /* z */) return ('A' + (ch - 0x2361));
  340.     } else {
  341.         cch = LOBYTE(ch);
  342.         for (i = 0; JAsciiEquivalents[i].ascii; i++) {
  343.             if (JAsciiEquivalents[i].ascii == cch) return (JAsciiEquivalents[i].kanji);
  344.         }
  345.         if ('A' <= cch && cch <= 'Z') return (0x2341 /* A */ + (cch - 'A'));
  346.         if ('a' <= cch && cch <= 'z') return (0x2361 /* a */ + (cch - 'a'));
  347.     }
  348.     return (0);
  349. }
  350.  
  351.  
  352.  
  353. char *ReverseKana (KANJI kana)
  354. {
  355.     int hi, lo;
  356.  
  357.     hi = HIBYTE(kana) & 0x7f;
  358.     lo = LOBYTE(kana) & 0x7f;
  359.  
  360.     if (hi != 0x24 && hi != 0x25) return (NULL);
  361.     if (lo < 0x21 && lo > 0x73) return (NULL);
  362.  
  363.     return (direct[lo - 0x21]);
  364.  
  365. }
  366.  
  367.  
  368.  
  369. void TurnOffSelection (FILEOPTIONS *f)
  370. {
  371.     if (SELPARA1(f) == NULL) return;
  372.  
  373.     FlipHighlight(f);
  374.     SELPARA1(f) = SELPARA2(f) = NULL;
  375.     SELPOS1(f) = SELPOS2(f) = 0;
  376.     SELNOW(f) = FALSE;
  377.     SELTYPE(f) = SEL_SELECTION;
  378.  
  379.     if (global.convsel >= 0 || kanji_list[0] != 0) {
  380.         global.convsel = -1;
  381.         kanji_list[0] = LastLen = LastConv[0] = 0;
  382.         SendMessage(global.convhwnd, LB_RESETCONTENT, 0, NULL);
  383.     }
  384. }
  385.  
  386.  
  387.  
  388. void FlipHighlight (FILEOPTIONS *f)
  389. {
  390.     int i, j, k, x, w;
  391.     int cgap, lgap;
  392.     KANJI c1, c2, c3;
  393.     BOOL insel = FALSE;
  394.     HDC hdc, fhdc;
  395.     POSITION p;
  396.  
  397.  
  398.     /* Does it start in a selection? */
  399.  
  400.     insel = InSelection(f, f->top);
  401.  
  402.     HideCaret(f->hwnd);
  403.  
  404.     lgap = LINEGAP(f);
  405.     cgap = CHARGAP(f);
  406.  
  407.     p = f->top;
  408.     j = LINEGAP(f);
  409.  
  410.     if (PREVLINE(p)) j -= LINEOF(p)->height + PARAOF(p)->spacing;
  411.  
  412.     fhdc = f->hdc;
  413.     f->hdc = hdc = GetDC(f->hwnd);
  414.  
  415.     do {
  416.         if (j + lgap > f->height) break;
  417.         j += LINEOF(p)->height;
  418.  
  419.         for (i = k = 0; k <= LINEOF(p)->length; k++) {
  420.             if (k == 0 && PARAOF(p) == SELPARA2(f) && &UNITOF(p,0) > &SELCHAR2(f)) {
  421.                 ReleaseDC(f->hwnd, hdc);
  422.                 ShowCaret(f->hwnd);
  423.                 return;
  424.             }
  425.  
  426.             if (LINEOF(p)->next != NULL && k == LINEOF(p)->length) break;
  427.  
  428.             x = i - f->startx + LEFTMARGIN(p) * BASEWIDTH(f);
  429.  
  430.             c1 = (k <= 0) ? 0 : CHAROF(p,k-1);
  431.             c2 = CHAROF(p,k);
  432.             c3 = (k < LINEOF(p)->length - 1) ? CHAROF(p,k+1) : 0;
  433.  
  434.             if (insel && (PARAOF(p) != SELPARA2(f) || LINEOF(p)->position + LINEOF(p)->length - 1 < SELPOS2(f))) {
  435.                 c3 = (LINEOF(p)->length > 0) ? CHAROF(p,LINEOF(p)->length - 1) : 0;
  436.                 if ((ISKANJI(c2) && c1 != '\t') || ISKANJI(c1) || (k <= 0 && LINEOF(p)->length > 0)) {
  437.                     PatBlt(hdc, x - cgap, j - LINEOF(p)->height - lgap,
  438.                             LINEOF(p)->width - f->startx - x + (ISKANJI(c3) ? 0 : cgap),
  439.                             LINEOF(p)->height + 2 * lgap, DSTINVERT);
  440.                 } else {
  441.                     PatBlt(hdc, x, j - LINEOF(p)->height - lgap,
  442.                             LINEOF(p)->width - f->startx - x,
  443.                             LINEOF(p)->height + 2 * lgap, DSTINVERT);
  444.                 }
  445.                 break;
  446.             } else if (!insel && PARAOF(p) == SELPARA1(f) && &UNITOF(p,k) >= &SELCHAR1(f)) {
  447.                 insel = TRUE;
  448.                 if (k >= LINEOF(p)->length) {
  449.                     /* Nothing */
  450.                 } else if ((k <= 0 && LINEOF(p)->length > 0) || (ISKANJI(c2) && c1 != '\t') || ISKANJI(c1)) {
  451.                     PatBlt(hdc, x - cgap, j - LINEOF(p)->height - lgap,
  452.                            cgap, LINEOF(p)->height + 2 * lgap, DSTINVERT);
  453.                 }
  454.             } else if (insel && k == 0 && LINEOF(p)->length > 0) {
  455.                 PatBlt(hdc, x - cgap, j - LINEOF(p)->height - lgap,
  456.                        cgap, LINEOF(p)->height + 2 * lgap, DSTINVERT);
  457.             } else if (insel && k > 0 && k < LINEOF(p)->length) {
  458.                 if ((ISKANJI(c2) && c1 != '\t') || ISKANJI(c1)) {
  459.                     PatBlt(hdc, x - f->leading + cgap, j - LINEOF(p)->height - lgap,
  460.                            f->leading - cgap, LINEOF(p)->height + 2 * lgap, DSTINVERT);
  461.                 }
  462.             }
  463.  
  464.             POSOF(p) = k;
  465.  
  466.             w = LOWORD(GetDimension(f, p, i));  /* Char width */
  467.  
  468.             if (insel) {
  469.                 if (c2 == '\t') {
  470.                     PatBlt(hdc, x, j - LINEOF(p)->height - lgap,
  471.                             w, LINEOF(p)->height + 2 * lgap, DSTINVERT);
  472.                 } else if (ISKANJI(c2) || ISKANJI(c3)) {
  473.                     PatBlt(hdc, x, j - LINEOF(p)->height - lgap,
  474.                             w + cgap, LINEOF(p)->height + 2 * lgap, DSTINVERT);
  475.                 } else {
  476.                     PatBlt(hdc, x, j - LINEOF(p)->height - lgap,
  477.                             w, LINEOF(p)->height + 2 * lgap, DSTINVERT);
  478.                 }
  479.  
  480.                 if (PARAOF(p) == SELPARA2(f) && &UNITOF(p,k) >= &SELCHAR2(f)) {
  481.                     ReleaseDC(f->hwnd, hdc);
  482.                     ShowCaret(f->hwnd);
  483.                     return;
  484.                 }
  485.             }
  486.  
  487.             i += w;
  488.  
  489.             if (c2 != '\t') {
  490.                 if (ISKANJI(c2) || ISKANJI(c3)) i += f->leading;
  491.             }
  492.         }
  493.  
  494.         j += PARAOF(p)->spacing;
  495.     } while (NEXTLINE(p));
  496.  
  497.     ReleaseDC(f->hwnd, hdc);
  498.     ShowCaret(f->hwnd);
  499.  
  500.     f->hdc = fhdc;
  501. }
  502.  
  503.  
  504.  
  505. void ReallocateText (POSITION p, unsigned int n)
  506. {
  507.     unsigned int len, size;
  508.  
  509.  
  510.     /* The optimal block size */
  511.  
  512.     size = (n * sizeof(UNIT)) / TEXTBLOCKSIZE;
  513.     size = (size + 1) * TEXTBLOCKSIZE;
  514.     len = size / sizeof(UNIT);
  515.  
  516.     if (PARAOF(p)->textsize == len) return;
  517.  
  518.  
  519.     /* Reallocate the block */
  520.  
  521.     PARAOF(p)->textsize = len;
  522.  
  523.     if (size >= C64K) {
  524.         ErrorMessage(global.hwnd, "Paragraph too large (%u)!\nCannot reallocate!", PARAOF(p)->textsize);
  525.         return;
  526.     }
  527.  
  528.     PARAOF(p)->text = BlockRealloc(PARAOF(p)->text, size);
  529. }
  530.  
  531.  
  532.  
  533. static BOOL InsideConversion (FILEOPTIONS *f, POSITION p)
  534. {
  535.     int abspos;
  536.  
  537.     if (SELPARA1(f) == NULL || SELPARA2(f) == NULL || SELTYPE(f) != SEL_CONVERSION)
  538.         return (0);
  539.  
  540.     if (SELPARA1(f) != PARAOF(p) || SELPARA2(f) != PARAOF(p)) return (0);
  541.  
  542.     abspos = POS2ABS(p);
  543.  
  544.     if (SELPOS1(f) == abspos) return (1);
  545.     if (SELPOS2(f) == abspos) return (3);
  546.     if (SELPOS1(f) <= abspos && abspos <= SELPOS2(f)) return (2);
  547.     if (abspos < SELPOS1(f)) return (0);
  548.     if (abspos > SELPOS2(f)) return (4);
  549.     return (0);
  550. }
  551.  
  552.  
  553.  
  554. void InsertString (FILEOPTIONS *f, POSITION p, KANJI far *buf, int Options)
  555. {
  556.     int i;
  557.     int len = kanjilen(buf);
  558.     UNIT far *cp;
  559.     ONELINE far *lp;
  560.  
  561.     if (len <= 0) return;
  562.  
  563.     if (!SELNOW(f)) {
  564.         switch (InsideConversion(f, p)) {
  565.             case 0: case 1: case 4: break;
  566.             case 2: case 3:         TurnOffSelection(f); break;
  567.         }
  568.     }
  569.  
  570.  
  571.     ReallocateText (p, unitlen(PARAOF(p)->text) + len + 1);
  572.  
  573.     cp = &UNITOF(f->current, CURCHAR(f));
  574.  
  575.     for (i = unitlen(PARAOF(p)->text) - LINEOF(p)->position; i >= POSOF(p); i--) {
  576.         UNITOF(p,i+len) = UNITOF(p,i);
  577.  
  578.         if (cp == &UNITOF(p,i)) CURCHAR(f) += len;
  579.  
  580.  
  581.         if (Options & OP_MOVESEL) {
  582.             if (SELPARA1(f) == PARAOF(p) && &UNITOF(p,i) == &SELCHAR1(f))
  583.                 SELPOS1(f) += len;
  584.             if (SELPARA2(f) == PARAOF(p) && &UNITOF(p,i) == &SELCHAR2(f))
  585.                 SELPOS2(f) += len;
  586.         }
  587.     }
  588.  
  589.     for (i = 0; i < len; i++) {
  590.         CHAROF(p,POSOF(p)+i) = buf[i];
  591.     }
  592.  
  593.     LINEOF(p)->length += len;
  594.     f->nr_bytes += len;
  595.  
  596.     for (lp = LINEOF(p)->next; lp != NULL; lp = lp->next) lp->position += len;
  597.  
  598.     if (Options & OP_REFORMAT)
  599.         ReformatParagraph(f, p, PARAOF(p)->next, Options);
  600.  
  601.     f->changed = TRUE;
  602. }
  603.  
  604.  
  605.  
  606. void DeleteString (FILEOPTIONS *f, POSITION p, int len, int Options)
  607. {
  608.     int i;
  609.     UNIT far *cp = &UNITOF(f->current, CURCHAR(f));
  610.     ONELINE far *lp;
  611.     POSITION tp;
  612.  
  613.     if (len <= 0) return;
  614.  
  615.     if (!SELNOW(f)) {
  616.         tp = p;
  617.         POSOF(tp) += (len - 1);
  618.  
  619.         switch (InsideConversion(f, p)) {
  620.             case 0: case 4: break;
  621.             case 1: case 2: case 3: TurnOffSelection(f); break;
  622.         }
  623.         switch (InsideConversion(f, tp)) {
  624.             case 0: case 4: break;
  625.             case 1: case 2: case 3: TurnOffSelection(f); break;
  626.         }
  627.         if (InsideConversion(f, p) == 0 && InsideConversion(f, tp) == 4)
  628.             TurnOffSelection(f);
  629.     }
  630.  
  631.  
  632.     i = unitlen(&UNITOF(p,POSOF(p)));
  633.     if (len > i) len = i;
  634.  
  635.  
  636.     if (Options & OP_MOVESEL) {
  637.         if (SELPARA1(f) == PARAOF(p) && &SELCHAR1(f) >= &UNITOF(p,POSOF(p)) &&
  638.             &SELCHAR1(f) < &UNITOF(p,POSOF(p)+len))
  639.                 SELPOS1(f) = LINEOF(p)->position + POSOF(p) + len;
  640.  
  641.         if (SELPARA2(f) == PARAOF(p) && &SELCHAR2(f) >= &UNITOF(p,POSOF(p)) &&
  642.             &SELCHAR2(f) < &UNITOF(p,POSOF(p)+len))
  643.                 SELPOS2(f) = LINEOF(p)->position + POSOF(p) - 1;
  644.  
  645.         if (SELPOS1(f) > SELPOS2(f)) {
  646.             SELPARA1(f) = SELPARA2(f) = NULL;
  647.             SELNOW(f) = FALSE;
  648.         }
  649.     }
  650.  
  651.  
  652.     if (PARAOF(p) == CURPARA(f) && &UNITOF(p,POSOF(p)) <= cp && &UNITOF(p,POSOF(p)+len) > cp) {
  653.         CURCHAR(f) = POSOF(p) + len;
  654.         cp = &UNITOF(p,CURCHAR(f));
  655.     }
  656.  
  657.  
  658.     for (i = POSOF(p); ; i++) {
  659.         UNITOF(p,i) = UNITOF(p,i+len);
  660.  
  661.         if (cp == &UNITOF(p,i+len)) {
  662.             CURLINE(f) = LINEOF(p);
  663.             CURCHAR(f) = i;
  664.         }
  665.  
  666.         if (Options & OP_MOVESEL) {
  667.             if (SELPARA1(f) == PARAOF(p) && &UNITOF(p,i+len) == &SELCHAR1(f))
  668.                 SELPOS1(f) -= len;
  669.             if (SELPARA2(f) == PARAOF(p) && &UNITOF(p,i+len) == &SELCHAR2(f))
  670.                 SELPOS2(f) -= len;
  671.         }
  672.  
  673.         if (!CHAROF(p,i)) break;
  674.     }
  675.     LINEOF(p)->length -= len;
  676.     f->nr_bytes -= len;
  677.  
  678.     for (lp = LINEOF(p)->next; lp != NULL; lp = lp->next) lp->position -= len;
  679.  
  680.     ReallocateText (p, unitlen(PARAOF(p)->text));
  681.  
  682.     if (Options & OP_REFORMAT)
  683.         ReformatParagraph(f, p, PARAOF(p)->next, Options);
  684.  
  685.     f->changed = TRUE;
  686. }
  687.  
  688.  
  689.  
  690. void ReplaceString (FILEOPTIONS *f, POSITION p, int len, KANJI far *buf, int Options)
  691. {
  692.     int i, gap;
  693.     POSITION p1;
  694.     int buflen = kanjilen(buf);
  695.     UNIT far *cp;
  696.  
  697.     if (buflen <= 0) {
  698.         DeleteString (f, p, len, Options);
  699.         return;
  700.     } else if (len <= 0) {
  701.         InsertString (f, p, buf, Options);
  702.         return;
  703.     }
  704.  
  705.  
  706.     if (!SELNOW(f) && !(Options & OP_CHOOSEKANJI)) {
  707.         p1 = p;
  708.         POSOF(p1) += (len - 1);
  709.  
  710.         switch (InsideConversion(f, p)) {
  711.             case 0: case 4: break;
  712.             case 1: case 2: case 3: TurnOffSelection(f); break;
  713.         }
  714.         switch (InsideConversion(f, p1)) {
  715.             case 0: case 4: break;
  716.             case 1: case 2: case 3: TurnOffSelection(f); break;
  717.         }
  718.         if (InsideConversion(f, p) == 0 && InsideConversion(f, p1) == 4)
  719.             TurnOffSelection(f);
  720.     }
  721.  
  722.  
  723.     gap = buflen - len;
  724.  
  725.     ReallocateText (p, unitlen(PARAOF(p)->text) + gap + 1);
  726.  
  727.     cp = &UNITOF(f->current, CURCHAR(f));
  728.  
  729.  
  730.     if (gap > 0) {          /* Lengthen */
  731.  
  732.         for (i = unitlen(PARAOF(p)->text) - LINEOF(p)->position; i >= POSOF(p); i--) {
  733.             UNITOF(p,i+gap) = UNITOF(p,i);
  734.  
  735.             if (cp == &UNITOF(p,i)) CURCHAR(f) += gap;
  736.  
  737.             if (Options & OP_MOVESEL) {
  738.                 if (SELPARA1(f) == PARAOF(p) && &UNITOF(p,i) == &SELCHAR1(f))
  739.                     SELPOS1(f) += gap;
  740.                 if (SELPARA2(f) == PARAOF(p) && &UNITOF(p,i) == &SELCHAR2(f))
  741.                     SELPOS2(f) += gap;
  742.             }
  743.         }
  744.         LINEOF(p)->length += gap;
  745.         f->nr_bytes += gap;
  746.     } else {
  747.         gap *= -1;
  748.  
  749.         for (i = POSOF(p); ; i++) {
  750.             UNITOF(p,i) = UNITOF(p,i+gap);
  751.  
  752.             if (cp == &UNITOF(p,i+gap)) {
  753.                 CURLINE(f) = LINEOF(p);
  754.                 CURCHAR(f) = i;
  755.             }
  756.  
  757.             if (Options & OP_MOVESEL) {
  758.                 if (SELPARA1(f) == PARAOF(p) && &UNITOF(p,i) == &SELCHAR1(f))
  759.                     SELPOS1(f) -= gap;
  760.                 if (SELPARA2(f) == PARAOF(p) && &UNITOF(p,i) == &SELCHAR2(f))
  761.                     SELPOS2(f) -= gap;
  762.             }
  763.  
  764.             if (!CHAROF(p,i)) break;
  765.         }
  766.         LINEOF(p)->length -= gap;
  767.         f->nr_bytes -= gap;
  768.     }
  769.  
  770.  
  771.     for (i = 0; i < buflen; i++) {
  772.         CHAROF(p,POSOF(p)+i) = buf[i];
  773.     }
  774.  
  775.  
  776.     f->changed = TRUE;
  777.  
  778.     if (!(Options & OP_REFORMAT)) return;
  779.  
  780.     Options &= ~OP_MINIMAL;
  781.     ReformatParagraph(f, p, PARAOF(p)->next, Options);
  782.     return;
  783. }
  784.  
  785.  
  786.  
  787. void ConvertNow (FILEOPTIONS *f, BOOL always)
  788. {
  789.     int i, j, r;
  790.     int len, convlen, choice;
  791.     POSITION p;
  792.     BOOL Now;
  793.  
  794.  
  795.     if (Typed[0]) CharInput(f, '\x07');     /* Bell */
  796.  
  797.     Now = SELNOW(f);
  798.  
  799.     if (!Now) {
  800.         KANJI convbuf[MAXLINELEN];
  801.  
  802.         /* Convert the selected text */
  803.  
  804.         for (i = 0; i <= SELPOS2(f) - SELPOS1(f); i++) {
  805.             KanjiBuffer[i] = SELPARA1(f)->text[SELPOS1(f)+i].kanji;
  806.             if (HIBYTE(KanjiBuffer[i]) != 0x24) {
  807.                 MessageBeep(0);
  808.                 return;
  809.             }
  810.         }
  811.         KanjiBuffer[i] = 0;
  812.  
  813.         r = FindConversion(KanjiBuffer, convbuf);
  814.  
  815.         if (r == 2 || r == 3) {         /* Exact match */
  816.             LastLen = kanjilen(KanjiBuffer);
  817.             kanjicpy(LastConv, convbuf);
  818.         } else {
  819.             MessageBeep(0);
  820.             return;
  821.         }
  822.     }
  823.  
  824.     AbsoluteToPosition (SEL1(f), &p);
  825.  
  826.     convlen = SELPOS2(f) - SELPOS1(f) + 1;
  827.  
  828.     if (kanjilen(LastConv) <= 0 || (!always && convlen > LastLen)) {
  829.         MessageBeep(0);
  830.         return;
  831.  
  832.         if (Now) {
  833.             SELPARA1(f) = SELPARA2(f) = NULL;
  834.             SELPOS1(f) = SELPOS2(f) = 0;
  835.             SELNOW(f) = FALSE;
  836.             UndoFixConvert(f, p, convlen, 0);
  837.             DeleteString(f, p, convlen, OP_REFORMAT | OP_UPDATE | OP_MOVETOEND | OP_CHOOSEKANJI);
  838.         }
  839.         return;
  840.     }
  841.  
  842.     kanjicpy(kanji_list, LastConv);
  843.     for (i = 0; i < convlen; i++) {
  844.         KanjiBuffer[i] = SELPARA1(f)->text[SELPOS1(f) + i].kanji;
  845.         LastConvKey[i] = LOBYTE(KanjiBuffer[i]);
  846.     }
  847.     KanjiBuffer[i] = 0;
  848.     LastConvKey[LastLen] = 0;
  849.  
  850.  
  851.     /* Is there a default? */
  852.  
  853.     choice = ConvCacheLookup(LastConvKey, kanji_list);
  854.  
  855.  
  856.     /* Put in the kana reading to the end */
  857.  
  858.     len = kanjilen(kanji_list);
  859.     if (len > 0 && kanji_list[len-1] != '/') {
  860.         kanji_list[len++] = '/';
  861.     }
  862.  
  863.     for (i = 0, j = len; i < LastLen; i++, j++) {
  864.         kanji_list[j] = KanjiBuffer[i];
  865.     }
  866.     //kanji_list[j++] = '/';
  867.     kanji_list[j] = 0;
  868.  
  869.  
  870.     /* Update the conversion list */
  871.  
  872.     global.convsel = (choice >= 0) ? choice : 0;
  873.     SendMessage(global.convhwnd, LB_RESETCONTENT, 0, (LONG) f);
  874.  
  875.  
  876.     /* Find that kanji word */
  877.  
  878.     for (i = j = 0; j < global.convsel && kanji_list[i]; i++)
  879.         if (kanji_list[i] == '/') j++;
  880.  
  881.     if (!kanji_list[i]) {
  882.         for (i--; i >= 0 && kanji_list[i] != '/'; i--);
  883.         i++;
  884.     } else {
  885.         if (kanji_list[i] == '/') i++;
  886.     }
  887.  
  888.     for (j = 0; kanji_list[i] != 0; i++, j++) {
  889.         if (kanji_list[i] == '/') break;
  890.         KanjiBuffer[j] = kanji_list[i];
  891.     }
  892.     KanjiBuffer[j] = 0;
  893.  
  894.     SELPOS2(f) = SELPOS1(f) + kanjilen(KanjiBuffer) - 1;
  895.  
  896.     for (i = LastLen; i < convlen; i++)
  897.         KanjiBuffer[j++] = SELPARA1(f)->text[SELPOS1(f)+i].kanji;
  898.     KanjiBuffer[j] = 0;
  899.  
  900.     if (SELPOS2(f) < SELPOS1(f)) {
  901.         SELPARA1(f) = SELPARA2(f) = NULL;
  902.         SELPOS1(f) = SELPOS2(f) = 0;
  903.     }
  904.  
  905.     if (Now) {
  906.         UndoFixConvert(f, p, convlen, kanjilen(KanjiBuffer));
  907.     } else {
  908.         POSITION p1, p2;
  909.  
  910.         p1 = p;
  911.         POSOF(p1) = POS2ABS(p1) + convlen;
  912.         AbsoluteToPosition(p1, &p2);
  913.         UndoAddReplace(f, p, p2);
  914.         POSOF(p1) += (kanjilen(KanjiBuffer) - convlen);
  915.         AbsoluteToPosition(p1, &p2);
  916.         UndoFixReplace(f, p2);
  917.     }
  918.  
  919.     ReplaceString(f, p, convlen, KanjiBuffer, OP_REFORMAT | OP_UPDATE | OP_MOVETOEND | OP_CHOOSEKANJI);
  920.  
  921.     SELNOW(f) = FALSE;
  922.     SELTYPE(f) = SEL_CONVERSION;
  923. }
  924.  
  925.  
  926. static void TestForGlossary(FILEOPTIONS *f, POSITION p, KANJI *InputBuffer)
  927. {
  928.     int i, j, r;
  929.     KANJI far *kp;
  930.     KANJI buffer[MAXLINELEN];
  931.  
  932.  
  933.     if (!global.dynamicglossary) return;
  934.  
  935.     for (i = 0; i <= Stackp; i++) {
  936.         if (i == Stackp) {
  937.             if (!InputBuffer[0]) break;
  938.             kanjicpy(buffer, InputBuffer);
  939.         } else {
  940.             for (j = 0; j <= GlossaryStack[i].length; j++) {
  941.                 buffer[j] = CURPARA(f)->text[GlossaryStack[i].offset + j].kanji;
  942.             }
  943.             buffer[j] = 0;
  944.         }
  945.  
  946.         r = SearchGlossary(buffer);
  947.  
  948.         if (r == -1) {          /* Partial match */
  949.             if (i == Stackp) {
  950.                 GlossaryStack[Stackp].offset = POS2ABS(p);
  951.                 GlossaryStack[Stackp].length = 1;
  952.                 if (Stackp >= STACKDEPTH) {
  953.                     ErrorMessage(global.hwnd, "The glossaries are too complicated!  "
  954.                                                  "Stack overflow.  Some matchings may be lost.");
  955.                 } else {
  956.                     Stackp++;
  957.                 }
  958.                 break;
  959.             } else {
  960.                 GlossaryStack[i].length++;
  961.             }
  962.         } else if (r == -2) {   /* No match */
  963.             if (i != Stackp) {
  964.                 /* Delete this */
  965.                 for (j = i + 1; j < Stackp; j++) GlossaryStack[j-1] = GlossaryStack[j];
  966.                 i--;
  967.                 Stackp--;
  968.             }
  969.         } else {                /* Exact match! */
  970.  
  971.             p = f->current;
  972.             POSOF(p) -= (GlossaryStack[i].length + 1);
  973.  
  974.             if (POSOF(p) < 0) {
  975.                 LINEOF(p) = LINEOF(p)->prev;
  976.                 POSOF(p) += LINEOF(p)->length;
  977.             }
  978.  
  979.             kp = GetGlossary(r);
  980.  
  981.             ReplaceString(f, p, GlossaryStack[i].length + 1, kp,
  982.                 OP_REFORMAT | OP_UPDATE | OP_MOVETOEND/* | OP_CHOOSEKANJI*/);
  983.  
  984.             UndoFixConvert(f, p, GlossaryStack[i].length + 1, kanjilen(kp));
  985.             Stackp = 0;
  986.             break;
  987.         }
  988.     }
  989. }
  990.  
  991.  
  992.  
  993. BOOL CharInput (FILEOPTIONS *f, WORD cch)
  994. {
  995.     int i, j, len, r;
  996.     int option = OP_MOVETOEND;
  997.     char ch;
  998.     BOOL loopback = FALSE;
  999.     BOOL allcaps;
  1000.     BOOL capitalized;
  1001.     POSITION p;
  1002.     KANJI convbuf[MAXLINELEN];
  1003.     UNIT far *cp;
  1004.     static int state = 0;
  1005.  
  1006.  
  1007.  
  1008.     ch = tolower(cch);
  1009.  
  1010.     /* Esc, Bell, Null, Backspace, Delete, Return */
  1011.  
  1012.     if (cch == 0 || cch == 0x07  /* Bell */) {
  1013.         Stackp = 0;
  1014.     } else if (Typed[0] && strchr("\x1b\b\x7f", cch) != NULL) {
  1015.         state = 0;
  1016.         Typed[0] = '\0';
  1017.         StatusMessage(Typed);
  1018.         return (FALSE);
  1019.     } else if ((cch == '\b' || cch == 127) && SELPARA1(f) != NULL && SELTYPE(f) != SEL_CONVERSION) {    /* Delete block */
  1020.         POSITION abs, start, stop;
  1021.  
  1022.         Stackp = 0;
  1023.  
  1024.         PARAOF(abs) = SELPARA1(f);
  1025.         POSOF(abs) = SELPOS1(f);
  1026.  
  1027.         AbsoluteToPosition(abs, &start);
  1028.  
  1029.         PARAOF(abs) = SELPARA2(f);
  1030.         POSOF(abs) = SELPOS2(f);
  1031.  
  1032.         AbsoluteToPosition(abs, &stop);
  1033.  
  1034.         /* Get rid of the selection */
  1035.  
  1036.         SELPARA1(f) = SELPARA2(f) = NULL;   SELPOS1(f) = SELPOS2(f) = 0;
  1037.         SELNOW(f) = FALSE;                  SELTYPE(f) = SEL_SELECTION;
  1038.  
  1039.  
  1040.         f->current = start;
  1041.  
  1042.         if (!FindCaret(f, FALSE)) {
  1043.             MoveIntoWindow(f);
  1044.             InvalidateRect(f->hwnd, NULL, TRUE);
  1045.             UpdateWindow(f->hwnd);
  1046.         }
  1047.  
  1048.         /* Move the cursor to the end */
  1049.  
  1050.         f->current = stop;
  1051.         if (CURCHAR(f) >= CURLINE(f)->length) {
  1052.             NEXTLINE(f->current);
  1053.         } else {
  1054.             CURCHAR(f)++;
  1055.         }
  1056.  
  1057.         UndoAddDelete(f, start, f->current);
  1058.         BlockDelete(f, start, stop);
  1059.     } else if (cch == '\b') {       /* Backspace */
  1060.         Stackp = 0;
  1061.  
  1062.         TakeCareOfThings(f, !SELNOW(f));
  1063.  
  1064.         if (CURCHAR(f) == 0 && CURLINE(f)->prev == NULL) {
  1065.             if (CURPARA(f)->prev != NULL) {
  1066.                 CURPARA(f) = CURPARA(f)->prev;
  1067.                 CURLINE(f) = CURPARA(f)->lastline;
  1068.                 CURCHAR(f) = CURLINE(f)->length;
  1069.  
  1070.                 /* Join two paragraphs */
  1071.                 InputBuffer[0] = '\b';
  1072.                 InputBuffer[1] = 0;
  1073.                 UndoJoinLine(f, f->current);
  1074.                 InsertString(f, f->current, InputBuffer,
  1075.                         OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND | OP_MINIMAL);
  1076.             }
  1077.         } else {
  1078.             option = OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MINIMAL;
  1079.  
  1080.             if (CURCHAR(f) <= 0) {
  1081.                 CURLINE(f) = CURLINE(f)->prev;
  1082.                 CURCHAR(f) = CURLINE(f)->length;
  1083.                 if (CHAROF(f->current,CURCHAR(f)) != '\n') CURCHAR(f)--;
  1084.                 if (CURCHAR(f) < 0) CURCHAR(f) = 0;
  1085.             } else {
  1086.                 CURCHAR(f)--;
  1087.             }
  1088.  
  1089.             cp = &UNITOF(f->current, CURCHAR(f));
  1090.  
  1091.             if (CURLINE(f)->prev != NULL && cp[-1].kanji != '\n' && cp[1].kanji == 0)
  1092.                 option |= OP_MOVETOEND;
  1093.  
  1094.             UndoAddErase(f, f->current, 1);
  1095.             DeleteString(f, f->current, 1, option);
  1096.         }
  1097.     } else if (cch == 127) {        /* Delete */
  1098.         Stackp = 0;
  1099.  
  1100.         if (UNITOF(f->current,CURCHAR(f)).kanji == 0) {
  1101.             if (CURPARA(f)->next != NULL) {
  1102.                 /* Join two paragraphs */
  1103.                 InputBuffer[0] = '\b';
  1104.                 InputBuffer[1] = 0;
  1105.  
  1106.                 UndoJoinLine(f, f->current);
  1107.                 InsertString(f, f->current, InputBuffer,
  1108.                     OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND | OP_MINIMAL);
  1109.             }
  1110.         } else {
  1111.             UndoAddErase(f, f->current, 1);
  1112.             DeleteString (f, f->current, 1,
  1113.                 OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MINIMAL);
  1114.         }
  1115.     } else if (!Typed[0] && cch == '\r') {       /* Return */
  1116.         Stackp = 0;
  1117.  
  1118.         if (!(f->type & FN_NORMAL)) return (FALSE);       /* Not in a file */
  1119.  
  1120.         if (SELNOW(f)) {
  1121.             ConvertNow(f, TRUE);
  1122.             cch = '\0';
  1123.         } else {
  1124.             InputBuffer[0] = '\r';
  1125.             InputBuffer[1] = 0;
  1126.             UndoAddTyping(f, f->current, 1, TRUE);
  1127.             InsertString(f, f->current, InputBuffer,
  1128.                 OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND | OP_MINIMAL);
  1129.         }
  1130.     } else if (!Typed[0] && cch == '\n') {       /* Soft return */
  1131.         Stackp = 0;
  1132.  
  1133.         if (!(f->type & FN_NORMAL)) return (FALSE);       /* Not in a file */
  1134.  
  1135.         if (SELNOW(f)) {
  1136.             ConvertNow(f, TRUE);
  1137.             cch = '\0';
  1138.         } else {
  1139.             InputBuffer[0] = '\n';
  1140.             InputBuffer[1] = 0;
  1141.  
  1142.             capitalized = allcaps = FALSE;
  1143.             option = 0;
  1144.  
  1145.             goto DoIns;
  1146.         }
  1147.     } else {
  1148.         /* Now check the allowed functions */
  1149.  
  1150.         if ((f->type & FN_EITHER) && f->nr_bytes > 0) {
  1151.             KANJI ch;
  1152.  
  1153.             ch = f->paragraph->text[0].kanji;
  1154.  
  1155.             switch (global.mode) {
  1156.                 case M_KANA:    if (ISKANJI(ch)) break;
  1157.                                 MessageBeep(0);
  1158.                                 return (TRUE);
  1159.  
  1160.                 case M_ASCII:   if (!ISKANJI(ch)) break;
  1161.                                 MessageBeep(0);
  1162.                                 return (TRUE);
  1163.             }
  1164.         }
  1165.     }
  1166.  
  1167.  
  1168. Loop:
  1169.  
  1170.     if (global.mode == M_ASCII && cch != '\t') {
  1171.         if ((cch >= ' ' && cch < 127) || (cch >= 128 + ' ' && cch < 255)) {
  1172.             InputBuffer[0] = cch;
  1173.             InputBuffer[1] = 0;
  1174.             p = f->current;
  1175.  
  1176.             if (SELPARA1(f) != NULL && SELTYPE(f) == SEL_SELECTION) {
  1177.                 POSITION p1, p2;
  1178.  
  1179.                 AbsoluteToPosition(SEL1(f), &p1);
  1180.                 f->current = p1;
  1181.                 if (!FindCaret(f, FALSE)) {
  1182.                     MoveIntoWindow(f);
  1183.                     InvalidateRect(f->hwnd, NULL, TRUE);
  1184.                     UpdateWindow(f->hwnd);
  1185.                 }
  1186.  
  1187.                 AbsoluteToPosition(SEL2(f), &p2);
  1188.                 f->current = p2;
  1189.                 if (CURCHAR(f) >= CURLINE(f)->length) {
  1190.                     NEXTLINE(f->current);
  1191.                 } else {
  1192.                     CURCHAR(f)++;
  1193.                 }
  1194.                 TakeCareOfThings(f, FALSE);
  1195.                 UndoAddReplace(f, p1, f->current);
  1196.                 BlockReplace(f, p1, p2, InputBuffer);
  1197.                 UndoFixReplace(f, f->current);
  1198.             } else {
  1199.                 TakeCareOfThings(f, FALSE);
  1200.                 UndoAddTyping(f, f->current, 1, FALSE);
  1201.                 InsertString(f, f->current, InputBuffer,
  1202.                     OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND | OP_MINIMAL);
  1203.             }
  1204.             TestForGlossary(f, p, InputBuffer);
  1205.         }
  1206.         return (TRUE);
  1207.     }
  1208.  
  1209.     len = strlen(Typed);
  1210.  
  1211.  
  1212.     /* Get the next state */
  1213.  
  1214.     for (i = 0; states[i].state >= 0 && states[i].state != state; i++);
  1215.  
  1216.     for (; states[i].state == state; i++) {
  1217.         if (strchr(states[i].input, ch) != NULL) break;
  1218.     }
  1219.  
  1220.     if (states[i].state != state) {
  1221.         if (state == 0) {
  1222.             Typed[0] = '\0';
  1223.  
  1224.             if (cch == '\t') InputBuffer[0] = '\t';
  1225.             else {
  1226.                 InputBuffer[0] = TranslateJAscii(cch, FALSE);
  1227.                 if (!InputBuffer[0]) {
  1228.                     StatusMessage (Typed);
  1229.                     return (FALSE);
  1230.                 }
  1231.             }
  1232.             InputBuffer[1] = 0;
  1233.             capitalized = allcaps = loopback = FALSE;
  1234.             goto DoIns;
  1235.         } else {
  1236.             state = 0;
  1237.             loopback = TRUE;
  1238.         }
  1239.     } else {
  1240.         if (cch >= ' ') Typed[len] = cch;
  1241.         Typed[++len] = '\0';
  1242.  
  1243.         state = states[i].next;
  1244.         if (state >= 0) {
  1245.             StatusMessage (Typed);
  1246.             return (FALSE);
  1247.         }
  1248.  
  1249.         loopback = FALSE;
  1250.     }
  1251.  
  1252.     /* Completed */
  1253.  
  1254.     if (strcmp(Typed, "N'")) {
  1255.         capitalized = isupper(Typed[0]);
  1256.         for (i = 0, allcaps = TRUE; Typed[i]; i++) {
  1257.             if (islower(Typed[i])) {
  1258.                 allcaps = FALSE;
  1259.                 break;
  1260.             }
  1261.         }
  1262.     } else {
  1263.         capitalized = FALSE;
  1264.         allcaps = TRUE;
  1265.     }
  1266.  
  1267.  
  1268.     StatusMessage(Typed);
  1269.  
  1270.     /* Translate the keystroke */
  1271.  
  1272.     if (loopback && len == 1 && Typed[0] == cch &&
  1273.         isalpha(Typed[0]) && strchr("AIUEOaiueo", cch) == NULL &&
  1274.         (!global.nnconvert || strchr("Nn", cch) == NULL)) {
  1275.  
  1276.         InputBuffer[0] = (allcaps ? 0x2521 : 0x2421) + FindDirect("+tu");
  1277.         InputBuffer[1] = 0;
  1278.     } else if (!loopback && len == 1 && strchr("AIUEO", Typed[0])) {
  1279.         state = -1;      /* Impossible state */
  1280.         return (FALSE);
  1281.     } else if (loopback && len == 1 && strchr("AIUEO",Typed[0]) != NULL) {
  1282.         AnsiLower(Typed);
  1283.         if (islower(cch) || cch == 0x07  /* Bell */) {
  1284.             capitalized = TRUE;
  1285.             allcaps = FALSE;
  1286.             InputBuffer[0] = 0x2421 + FindDirect(Typed);
  1287.         } else {
  1288.             /* An upper case follows capital A I U E O */
  1289.             loopback = TRUE;
  1290.             state = 0;
  1291.             InputBuffer[0] = 0x2521 + FindDirect(Typed);
  1292.             capitalized = FALSE;
  1293.             allcaps = TRUE;
  1294.         }
  1295.         InputBuffer[1] = 0;
  1296.     } else if (len == 3 && tolower(Typed[0]) != 'd' && Typed[0] != '+' && tolower(Typed[1]) == 'y') {
  1297.         AnsiLower(Typed);
  1298.         if (Typed[2] == 'e') {
  1299.             strcpy(Temp, "+e");
  1300.         } else {
  1301.             strcpy(Temp, Typed);
  1302.         }
  1303.         Temp[0] = '+';
  1304.         Typed[1] = 'i';
  1305.         Typed[2] = '\0';
  1306.         if (Typed[0] == 'z') Typed[0] = 'j';
  1307.  
  1308.         InputBuffer[0] = (allcaps ? 0x2521 : 0x2421) + FindDirect(Typed);
  1309.         InputBuffer[1] = (allcaps ? 0x2521 : 0x2421) + FindDirect(Temp);
  1310.  
  1311.         InputBuffer[2] = 0;
  1312.     } else {
  1313.         AnsiLower(Typed);
  1314.         for (i = 0; ComposedEquivalents[i].string != NULL; i++) {
  1315.             if (!strcmp(ComposedEquivalents[i].string, Typed)) break;
  1316.         }
  1317.         if (ComposedEquivalents[i].string != NULL) {
  1318.             if (ComposedEquivalents[i].real[0] != '[') {
  1319.                 for (j = 0; ComposedEquivalents[i].real[j]; j++)
  1320.                     InputBuffer[j] = (allcaps ? 0x2500 : 0x2400) + ComposedEquivalents[i].real[j];
  1321.                 InputBuffer[j] = 0;
  1322.             } else {
  1323.                 int t;
  1324.  
  1325.                 for (t = 0; ComposedEquivalents[i].real[t + 1] != ']'; t += 2) {
  1326.                     InputBuffer[t/2] = (ComposedEquivalents[i].real[t + 1] << 8) | ComposedEquivalents[i].real[t + 2];
  1327.                 }
  1328.                 InputBuffer[t/2] = 0;
  1329.             }
  1330.         } else {
  1331.             j = FindDirect(Typed);
  1332.             if (j < 0) {
  1333.                 Typed[0] = '\0';
  1334.                 if (loopback) goto Loop;
  1335.                 return (FALSE);
  1336.             }
  1337.             InputBuffer[0] = (allcaps ? 0x2521 : 0x2421) + j;
  1338.             InputBuffer[1] = 0;
  1339.         }
  1340.     }
  1341.  
  1342.  
  1343. DoIns:
  1344.  
  1345.     state = 0;
  1346.     Typed[0] = '\0';
  1347.  
  1348.     if (SELNOW(f) && capitalized && !(f->type & FN_NOKANJI)) ConvertNow(f, TRUE);
  1349.  
  1350.     if (SELNOW(f)) {
  1351.         SELPOS2(f) += kanjilen(InputBuffer);
  1352.     } else if (capitalized && !allcaps && !(f->type & FN_NOKANJI)) {
  1353.         FlipHighlight(f);
  1354.         SELPARA1(f) = SELPARA2(f) = CURPARA(f);
  1355.         SELPOS1(f) = CURLINE(f)->position + CURCHAR(f);
  1356.         SELPOS2(f) = SELPOS1(f) + kanjilen(InputBuffer) - 1;
  1357.         SELNOW(f) = TRUE;
  1358.         SELTYPE(f) = SEL_CONVERSION;
  1359.         global.convsel = -1;
  1360.         kanji_list[0] = LastLen = LastConv[0] = 0;
  1361.         SendMessage(global.convhwnd, LB_RESETCONTENT, 0, NULL);
  1362.     }
  1363.  
  1364.     if (!f->caret) {
  1365.         MoveIntoWindow(f);
  1366.         InvalidateRect(f->hwnd, NULL, TRUE);
  1367.         UpdateWindow(f->hwnd);
  1368.     }
  1369.  
  1370.  
  1371.     /* may start as 0 or OP_MOVETOEND */
  1372.  
  1373.     option |= (OP_REFORMAT | OP_UPDATE | OP_MINIMAL);
  1374.     if (!SELNOW(f)) option |= OP_MOVESEL;
  1375.  
  1376.     p = f->current;
  1377.  
  1378.     /* Replace? */
  1379.  
  1380.     if (SELPARA1(f) != NULL && SELTYPE(f) == SEL_SELECTION) {
  1381.         POSITION p1, p2;
  1382.  
  1383.         AbsoluteToPosition(SEL1(f), &p1);
  1384.         f->current = p1;
  1385.         if (!FindCaret(f, FALSE)) {
  1386.             MoveIntoWindow(f);
  1387.             InvalidateRect(f->hwnd, NULL, TRUE);
  1388.             UpdateWindow(f->hwnd);
  1389.         }
  1390.  
  1391.         AbsoluteToPosition(SEL2(f), &p2);
  1392.         f->current = p2;
  1393.         if (CURCHAR(f) >= CURLINE(f)->length) {
  1394.             NEXTLINE(f->current);
  1395.         } else {
  1396.             CURCHAR(f)++;
  1397.         }
  1398.         TakeCareOfThings(f, FALSE);
  1399.         UndoAddReplace(f, p1, f->current);
  1400.         BlockReplace(f, p1, p2, InputBuffer);
  1401.         UndoFixReplace(f, f->current);
  1402.     } else {
  1403.         TakeCareOfThings(f, FALSE);
  1404.         UndoAddTyping(f, f->current, kanjilen(InputBuffer), FALSE);
  1405.         InsertString(f, f->current, InputBuffer, option);
  1406.     }
  1407.  
  1408.     if (SELNOW(f)) {
  1409.         /* Is kana? */
  1410.  
  1411.         if (HIBYTE(SELCHAR2(f).kanji) == 0x24) {
  1412.             for (i = 0; i <= SELPOS2(f) - SELPOS1(f); i++)
  1413.                 KanjiBuffer[i] = SELPARA1(f)->text[SELPOS1(f)+i].kanji;
  1414.             KanjiBuffer[i] = 0;
  1415.  
  1416.             r = FindConversion(KanjiBuffer, convbuf);
  1417.         } else {
  1418.             r = 0;
  1419.         }
  1420.  
  1421.         if (r == 2 || r == 3) {         /* Exact match */
  1422.             LastLen = kanjilen(KanjiBuffer);
  1423.             kanjicpy(LastConv, convbuf);
  1424.         }
  1425.  
  1426.         if (r == 0 || r == 2) {         /* No future hope */
  1427.             ConvertNow(f, TRUE);
  1428.         } else if (global.dynamicconvert) {
  1429.             kanjicpy(kanji_list, convbuf);
  1430.             SendMessage(global.convhwnd, LB_RESETCONTENT, 0, (LONG) f);
  1431.         }
  1432.     } else {
  1433.         TestForGlossary(f, p, InputBuffer);
  1434.     }
  1435.  
  1436.     if (loopback) goto Loop;
  1437.  
  1438.     StatusMessage (Typed);
  1439.  
  1440.     return (TRUE);
  1441. }
  1442.