00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "config.h"
00014 #include "vi.h"
00015 #include "ctype.h"
00016
00017
00018
00019 int vgets(prompt, buf, bsize)
00020 char prompt;
00021 char *buf;
00022 int bsize;
00023 {
00024 int len;
00025 int ch;
00026 int quoted;
00027 int tab;
00028 char widths[132];
00029 int word;
00030 #ifndef NO_DIGRAPH
00031 int erased;
00032 #endif
00033
00034
00035 move(LINES - 1, 0);
00036 tab = 0;
00037 if (prompt)
00038 {
00039 addch(prompt);
00040 tab = 1;
00041 }
00042 clrtoeol();
00043 refresh();
00044
00045
00046 #ifndef NO_DIGRAPH
00047 erased =
00048 #endif
00049 quoted = len = 0;
00050 for (;;)
00051 {
00052 #ifndef NO_ABBR
00053 if (quoted || mode == MODE_EX)
00054 {
00055 ch = getkey(0);
00056 }
00057 else
00058 {
00059
00060 for (word = len; --word >= 0 && isalnum(buf[word]); )
00061 {
00062 }
00063 word++;
00064 ch = getabkey(WHEN_EX, &buf[word], len - word);
00065 }
00066 #else
00067 ch = getkey(0);
00068 #endif
00069 #ifndef NO_EXTENSIONS
00070 if (ch == ctrl('O'))
00071 {
00072 ch = getkey(quoted ? 0 : WHEN_EX);
00073 }
00074 #endif
00075
00076
00077 if (ch == ctrl('D') && len == 0)
00078 ch = ctrl('[');
00079 #ifndef NO_DIGRAPH
00080 if (*o_digraph && erased != 0 && ch != '\b')
00081 {
00082 ch = digraph(erased, ch);
00083 erased = 0;
00084 }
00085 #endif
00086
00087
00088 if (quoted && ch != '\n')
00089 {
00090 ch |= 256;
00091 }
00092
00093
00094 switch(ch)
00095 {
00096 case ctrl('V'):
00097 qaddch('^');
00098 qaddch('\b');
00099 quoted = TRUE;
00100 break;
00101
00102 case ctrl('['):
00103 return -1;
00104
00105 case '\n':
00106 #if OSK
00107 case '\l':
00108 #else
00109 case '\r':
00110 #endif
00111 clrtoeol();
00112 goto BreakBreak;
00113
00114 case '\b':
00115 if (len > 0)
00116 {
00117 len--;
00118 #ifndef NO_DIGRAPH
00119 erased = buf[len];
00120 #endif
00121 for (ch = widths[len]; ch > 0; ch--)
00122 addch('\b');
00123 if (mode == MODE_EX)
00124 {
00125 clrtoeol();
00126 }
00127 tab -= widths[len];
00128 }
00129 else
00130 {
00131 return -1;
00132 }
00133 break;
00134
00135 default:
00136
00137 if (ch & 256)
00138 {
00139 ch &= ~256;
00140 qaddch(' ');
00141 qaddch('\b');
00142 }
00143
00144
00145 if (len < bsize - 1)
00146 {
00147 if (ch == '\t' && !quoted)
00148 {
00149 widths[len] = *o_tabstop - (tab % *o_tabstop);
00150 addstr(" " + 8 - widths[len]);
00151 tab += widths[len];
00152 }
00153 else if (ch > 0 && ch < ' ')
00154 {
00155 addch('^');
00156 addch(ch + '@');
00157 widths[len] = 2;
00158 tab += 2;
00159 }
00160 else if (ch == '\177')
00161 {
00162 addch('^');
00163 addch('?');
00164 widths[len] = 2;
00165 tab += 2;
00166 }
00167 else
00168 {
00169 addch(ch);
00170 widths[len] = 1;
00171 tab++;
00172 }
00173 buf[len++] = ch;
00174 }
00175 else
00176 {
00177 beep();
00178 }
00179 quoted = FALSE;
00180 }
00181 }
00182 BreakBreak:
00183 refresh();
00184 buf[len] = '\0';
00185 return len;
00186 }
00187
00188
00189 static int manymsgs;
00190 static char pmsg[80];
00191
00192
00193 static int showmsg()
00194 {
00195
00196 if (!manymsgs)
00197 return FALSE;
00198
00199
00200 move(LINES - 1, 0);
00201 if (*pmsg)
00202 {
00203 standout();
00204 qaddch(' ');
00205 qaddstr(pmsg);
00206 qaddch(' ');
00207 standend();
00208 }
00209 clrtoeol();
00210
00211 manymsgs = FALSE;
00212 return TRUE;
00213 }
00214
00215
00216 void endmsgs()
00217 {
00218 if (manymsgs)
00219 {
00220 showmsg();
00221 addch('\n');
00222 }
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 void msg(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
00240 char *fmt;
00241 long arg1, arg2, arg3, arg4, arg5, arg6, arg7;
00242 {
00243 if (mode != MODE_VI)
00244 {
00245 sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
00246 qaddstr(pmsg);
00247 addch('\n');
00248 exrefresh();
00249 }
00250 else
00251 {
00252
00253 if (manymsgs)
00254 {
00255 getkey(WHEN_MSG);
00256 }
00257
00258
00259 sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
00260 if (*fmt)
00261 {
00262 manymsgs = TRUE;
00263 }
00264 }
00265 }
00266
00267
00268
00269 void exrefresh()
00270 {
00271 char *scan;
00272
00273
00274
00275
00276 for (scan=kbuf; scan<stdscr; scan++)
00277 if (*scan == '\n')
00278 exwrote = TRUE;
00279
00280
00281 if (*o_exrefresh)
00282 {
00283 refresh();
00284 }
00285 else
00286 {
00287 wqrefresh();
00288 }
00289 if (mode != MODE_VI)
00290 {
00291 manymsgs = FALSE;
00292 }
00293 }
00294
00295
00296
00297
00298
00299
00300 typedef struct _map
00301 {
00302 struct _map *next;
00303 short len;
00304 short flags;
00305 char *label;
00306 char *rawin;
00307 char *cooked;
00308 } MAP;
00309
00310 static char keybuf[KEYBUFSIZE];
00311 static int cend;
00312 static int user;
00313 static int next;
00314 static MAP *match;
00315 static MAP *maps;
00316 #ifndef NO_ABBR
00317 static MAP *abbrs;
00318 #endif
00319
00320
00321
00322
00323 void beep()
00324 {
00325
00326 if (*o_flash)
00327 {
00328 do_VB();
00329 refresh();
00330 }
00331 else if (*o_errorbells)
00332 {
00333 ttywrite("\007", 1);
00334 }
00335
00336
00337 next = user = cend;
00338 }
00339
00340
00341
00342
00343
00344
00345 void execmap(rawlen, cookedstr, visual)
00346 int rawlen;
00347 char *cookedstr;
00348 int visual;
00349 {
00350 int cookedlen;
00351 char *src, *dst;
00352 int i;
00353
00354
00355 cookedlen = strlen(cookedstr);
00356 #ifndef NO_EXTENSIONS
00357 if (visual)
00358 {
00359 cookedlen *= 2;
00360 }
00361 #endif
00362
00363
00364 if (cookedlen + (cend - next) - rawlen > KEYBUFSIZE)
00365 {
00366 return;
00367 }
00368
00369
00370 src = &keybuf[next + rawlen];
00371 dst = &keybuf[cookedlen];
00372 i = cend - (next + rawlen);
00373 if (src >= dst)
00374 {
00375 while (i-- > 0)
00376 {
00377 *dst++ = *src++;
00378 }
00379 }
00380 else
00381 {
00382 src += i;
00383 dst += i;
00384 while (i-- > 0)
00385 {
00386 *--dst = *--src;
00387 }
00388 }
00389
00390
00391 cend += cookedlen - rawlen - next;
00392 user += cookedlen - rawlen - next;
00393 next = 0;
00394 for (dst = keybuf, src = cookedstr; *src; )
00395 {
00396 #ifndef NO_EXTENSIONS
00397 if (visual)
00398 {
00399 *dst++ = ctrl('O');
00400 cookedlen--;
00401 }
00402 #endif
00403 *dst++ = *src++;
00404 }
00405
00406 #ifdef DEBUG2
00407 {
00408 #include <stdio.h>
00409 FILE *debout;
00410 int i;
00411
00412 debout = fopen("debug.out", "a");
00413 fprintf(debout, "After execmap(%d, \"%s\", %d)...\n", rawlen, cookedstr, visual);
00414 for (i = 0; i < cend; i++)
00415 {
00416 if (i == next) fprintf(debout, "(next)");
00417 if (i == user) fprintf(debout, "(user)");
00418 if (UCHAR(keybuf[i]) < ' ')
00419 fprintf(debout, "^%c", keybuf[i] ^ '@');
00420 else
00421 fprintf(debout, "%c", keybuf[i]);
00422 }
00423 fprintf(debout, "(end)\n");
00424 fclose(debout);
00425 }
00426 #endif
00427 }
00428
00429
00430
00431
00432
00433
00434 static int fillkeybuf(when, timeout)
00435 int when;
00436 int timeout;
00437 {
00438 int nkeys;
00439 #ifndef NO_SHOWMODE
00440 static int oldwhen;
00441 static int oldleft;
00442 static long oldtop;
00443 static long oldnlines;
00444 char *str;
00445 #endif
00446 #ifndef NO_CURSORSHAPE
00447 static int oldcurs;
00448 #endif
00449
00450 #ifdef DEBUG
00451 watch();
00452 #endif
00453
00454
00455 #ifndef NO_CURSORSHAPE
00456
00457 if (has_CQ)
00458 {
00459 if (when != oldcurs)
00460 {
00461 switch (when)
00462 {
00463 case WHEN_EX: do_CX(); break;
00464 case WHEN_VICMD: do_CV(); break;
00465 case WHEN_VIINP: do_CI(); break;
00466 case WHEN_VIREP: do_CR(); break;
00467 }
00468 oldcurs = when;
00469 }
00470 }
00471 #endif
00472
00473 #ifndef NO_SHOWMODE
00474
00475 if (*o_smd && (when & WHENMASK))
00476 {
00477
00478
00479
00480 redraw(cursor, !(when & WHEN_VICMD));
00481
00482
00483 if (when != oldwhen || topline != oldtop || leftcol != oldleft || nlines != oldnlines)
00484 {
00485 oldwhen = when;
00486 oldtop = topline;
00487 oldleft = leftcol;
00488 oldnlines = nlines;
00489
00490 if (when & WHEN_VICMD) str = "Command";
00491 else if (when & WHEN_VIINP) str = " Input ";
00492 else if (when & WHEN_VIREP) str = "Replace";
00493 else if (when & WHEN_REP1) str = " Rep 1 ";
00494 else if (when & WHEN_CUT) str = "BufName";
00495 else if (when & WHEN_MARK) str = "Mark AZ";
00496 else if (when & WHEN_CHAR) str = "Dest Ch";
00497 else str = (char *)0;
00498
00499 if (str)
00500 {
00501 move(LINES - 1, COLS - 10);
00502 standout();
00503 qaddstr(str);
00504 standend();
00505 }
00506 }
00507 }
00508 #endif
00509
00510 #ifndef NO_EXTENSIONS
00511
00512 if (*o_ruler && (when & (WHEN_VICMD|WHEN_VIINP|WHEN_VIREP)))
00513 {
00514 char buf[20];
00515
00516 redraw(cursor, !(when & WHEN_VICMD));
00517 pfetch(markline(cursor));
00518 sprintf(buf, "%7ld,%-4d", markline(cursor), 1 + idx2col(cursor, ptext, when & (WHEN_VIINP|WHEN_VIREP)));
00519 move(LINES - 1, COLS - 22);
00520 addstr(buf);
00521 }
00522 #endif
00523
00524
00525 if (when & WHENMASK)
00526 {
00527 redraw(cursor, !(when & (WHENMASK & ~(WHEN_VIREP|WHEN_VIINP))));
00528 }
00529
00530
00531 refresh();
00532 nkeys = ttyread(keybuf + cend, sizeof keybuf - cend, timeout);
00533
00534
00535 if (nkeys == 0 && timeout == 0)
00536 {
00537 tmpabort(TRUE);
00538 move(LINES - 1, 0);
00539 clrtoeol();
00540 refresh();
00541 endwin();
00542 exit(1);
00543 }
00544
00545 cend += nkeys;
00546 user += nkeys;
00547 return nkeys;
00548 }
00549
00550
00551
00552
00553
00554
00555 static int countmatch(when)
00556 int when;
00557 {
00558 MAP *map;
00559 int count;
00560
00561
00562 match = (MAP *)0;
00563
00564
00565 for (count = 0, map = maps; map; map = map->next)
00566 {
00567
00568 if ((map->flags & when) == 0)
00569 {
00570 continue;
00571 }
00572
00573
00574 if (map->len <= cend - next)
00575 {
00576
00577 if (!strncmp(map->rawin, &keybuf[next], map->len))
00578 {
00579 count++;
00580
00581
00582
00583
00584 if (!match || match->len < map->len)
00585 {
00586 match = map;
00587 }
00588 }
00589 }
00590 else
00591 {
00592
00593 if (!strncmp(map->rawin, &keybuf[next], cend - next))
00594 {
00595 count++;
00596 }
00597 }
00598 }
00599 return count;
00600 }
00601
00602
00603 #ifndef NO_ABBR
00604
00605
00606
00607
00608 static void expandabbr(word, wlen)
00609 char *word;
00610 int wlen;
00611 {
00612 MAP *abbr;
00613
00614
00615 if (isalnum(keybuf[next]) || keybuf[next] == ctrl('V'))
00616 {
00617 return;
00618 }
00619
00620
00621 for (abbr = abbrs;
00622 abbr && (abbr->len != wlen || strncmp(abbr->rawin, word, wlen));
00623 abbr = abbr->next)
00624 {
00625 }
00626
00627
00628
00629
00630
00631 if (abbr)
00632 {
00633 execmap(0, abbr->cooked, FALSE);
00634 while (wlen > 15)
00635 {
00636 execmap(0, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", FALSE);
00637 wlen -= 15;
00638 }
00639 if (wlen > 0)
00640 {
00641 execmap(0, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" + 15 - wlen, FALSE);
00642 }
00643 }
00644 }
00645 #endif
00646
00647
00648
00649 int getkey(when)
00650 int when;
00651 {
00652 return getabkey(when, "", 0);
00653 }
00654
00655
00656
00657
00658
00659 int getabkey(when, word, wlen)
00660 int when;
00661 char *word;
00662 int wlen;
00663 {
00664 int matches;
00665
00666
00667
00668
00669 if (showmsg())
00670 {
00671 if (when == WHEN_MSG)
00672 {
00673 #ifndef CRUNCH
00674 if (!*o_more)
00675 {
00676 refresh();
00677 return ' ';
00678 }
00679 #endif
00680 qaddstr("[More...]");
00681 refresh();
00682 execmap(user, "", FALSE);
00683 }
00684 }
00685
00686 #ifdef DEBUG
00687
00688 watch();
00689 #endif
00690
00691
00692 if (next >= cend)
00693 {
00694 next = user = cend = 0;
00695 fillkeybuf(when, 0);
00696 }
00697
00698
00699 if (next >= user || *o_remap)
00700 {
00701 do
00702 {
00703 do
00704 {
00705 matches = countmatch(when);
00706 } while (matches > 1 && fillkeybuf(when, *o_keytime) > 0);
00707 if (matches == 1)
00708 {
00709 execmap(match->len, match->cooked,
00710 (match->flags & WHEN_INMV) != 0
00711 && (when & (WHEN_VIINP|WHEN_VIREP)) != 0);
00712 }
00713 } while (*o_remap && matches == 1);
00714 }
00715
00716 #ifndef NO_ABBR
00717
00718 if (wlen > 0 && (mode & (WHEN_EX|WHEN_VIINP|WHEN_VIREP)) != 0)
00719 {
00720 expandabbr(word, wlen);
00721 }
00722 #endif
00723
00724
00725 if (keybuf[next] == ERASEKEY)
00726 {
00727 keybuf[next] = '\b';
00728 }
00729
00730
00731 return keybuf[next++];
00732 }
00733
00734
00735 void mapkey(rawin, cooked, when, name)
00736 char *rawin;
00737 char *cooked;
00738 short when;
00739 char *name;
00740 {
00741 MAP **head;
00742 MAP *scan;
00743 MAP *prev;
00744
00745
00746 #ifndef NO_ABBR
00747 head = ((!name || strcmp(name, "abbr")) ? &maps : &abbrs);
00748 #else
00749 head = &maps;
00750 #endif
00751
00752
00753 for (scan = *head, prev = (MAP *)0;
00754 scan && (strcmp(rawin, scan->rawin) ||
00755 !(scan->flags & when & (WHEN_EX|WHEN_VICMD|WHEN_VIINP|WHEN_VIREP)));
00756 prev = scan, scan = scan->next)
00757 {
00758 }
00759
00760
00761 if (cooked && *cooked)
00762 {
00763
00764 if (head == &maps && !strncmp(cooked, "visual ", 7))
00765 {
00766 cooked += 7;
00767 when |= WHEN_INMV;
00768 }
00769
00770
00771 if (when & WHEN_INMV)
00772 {
00773 when |= WHEN_VIINP|WHEN_VIREP|WHEN_POPUP;
00774 }
00775
00776
00777 if (!scan)
00778 {
00779 scan = (MAP *)malloc(sizeof(MAP));
00780 scan->len = strlen(rawin);
00781 scan->rawin = malloc(scan->len + 1);
00782 strcpy(scan->rawin, rawin);
00783 scan->flags = when;
00784 scan->label = name;
00785 if (*head)
00786 {
00787 prev->next = scan;
00788 }
00789 else
00790 {
00791 *head = scan;
00792 }
00793 scan->next = (MAP *)0;
00794 }
00795 else
00796 {
00797 free(scan->cooked);
00798 }
00799 scan->cooked = malloc(strlen(cooked) + 1);
00800 strcpy(scan->cooked, cooked);
00801 }
00802 else
00803 {
00804
00805 if (!scan)
00806 {
00807 return;
00808 }
00809
00810
00811 if (prev)
00812 {
00813 prev->next = scan->next;
00814 }
00815 else
00816 {
00817 *head = scan->next;
00818 }
00819
00820
00821 free(scan->rawin);
00822 free(scan->cooked);
00823 free(scan);
00824 }
00825 }
00826
00827
00828
00829 char *printable(str)
00830 char *str;
00831 {
00832 char *build;
00833
00834 for (build = tmpblk.c; *str; str++)
00835 {
00836 #if AMIGA
00837 if (*str == '\233')
00838 {
00839 *build++ = '<';
00840 *build++ = 'C';
00841 *build++ = 'S';
00842 *build++ = 'I';
00843 *build++ = '>';
00844 } else
00845 #endif
00846 if (UCHAR(*str) < ' ' || *str == '\177')
00847 {
00848 *build++ = '^';
00849 *build++ = *str ^ '@';
00850 }
00851 else
00852 {
00853 *build++ = *str;
00854 }
00855 }
00856 *build = '\0';
00857 return tmpblk.c;
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867 void dumpkey(when, abbr)
00868 int when;
00869 int abbr;
00870 {
00871 MAP *scan;
00872 char *str;
00873 int len;
00874
00875 #ifndef NO_ABBR
00876 for (scan = (abbr ? abbrs : maps); scan; scan = scan->next)
00877 #else
00878 for (scan = maps; scan; scan = scan->next)
00879 #endif
00880 {
00881
00882 if ((scan->flags & when) == 0)
00883 {
00884 continue;
00885 }
00886
00887
00888 if (!abbr)
00889 {
00890 len = 8;
00891 if (scan->label)
00892 {
00893 qaddstr(scan->label);
00894 len -= strlen(scan->label);
00895 }
00896 do
00897 {
00898 qaddch(' ');
00899 } while (len-- > 0);
00900 }
00901
00902
00903 str = printable(scan->rawin);
00904 qaddstr(str);
00905 len = strlen(str);
00906 do
00907 {
00908 qaddch(' ');
00909 } while (len++ < 8);
00910
00911
00912 #ifndef NO_EXTENSIONS
00913 if ((scan->flags & WHEN_INMV) && (when & (WHEN_VIINP|WHEN_VIREP)))
00914 {
00915 qaddstr("visual ");
00916 }
00917 #endif
00918 str = printable(scan->cooked);
00919 qaddstr(str);
00920 addch('\n');
00921 exrefresh();
00922 }
00923 }
00924
00925 #ifndef NO_MKEXRC
00926
00927 static safequote(str)
00928 char *str;
00929 {
00930 char *build;
00931
00932 build = tmpblk.c + strlen(tmpblk.c);
00933 while (*str)
00934 {
00935 if (*str <= ' ' && *str >= 1 || *str == '|')
00936 {
00937 *build++ = ctrl('V');
00938 }
00939 *build++ = *str++;
00940 }
00941 *build = '\0';
00942 }
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 savemaps(fd, abbr)
00953 int fd;
00954 int abbr;
00955 {
00956 MAP *scan;
00957 char *str;
00958 int bang;
00959 int when;
00960 int len;
00961
00962 # ifndef NO_ABBR
00963 for (scan = (abbr ? abbrs : maps); scan; scan = scan->next)
00964 # else
00965 for (scan = maps; scan; scan = scan->next)
00966 # endif
00967 {
00968
00969 if (scan->label && *scan->label != '#')
00970 {
00971 continue;
00972 }
00973
00974 for (bang = 0; bang < 2; bang++)
00975 {
00976
00977 # ifndef NO_ABBR
00978 if (abbr)
00979 when = (bang ? WHEN_EX|WHEN_VIINP|WHEN_VIREP : WHEN_VIINP|WHEN_VIREP);
00980 else
00981 # endif
00982 when = (bang ? WHEN_VIREP|WHEN_VIINP : WHEN_VICMD);
00983
00984
00985 if ((scan->flags & when) == 0)
00986 {
00987 continue;
00988 }
00989
00990
00991 # ifndef NO_ABBR
00992 if (abbr)
00993 strcpy(tmpblk.c, "abbr");
00994 else
00995 # endif
00996 strcpy(tmpblk.c, "map");
00997
00998
00999 if (bang)
01000 strcat(tmpblk.c, "! ");
01001 else
01002 strcat(tmpblk.c, " ");
01003
01004
01005 # ifndef NO_FKEY
01006 if (scan->label)
01007 strcat(tmpblk.c, scan->label);
01008 else
01009 # endif
01010 safequote(scan->rawin);
01011 strcat(tmpblk.c, " ");
01012
01013
01014 # ifndef NO_EXTENSIONS
01015 if ((scan->flags & WHEN_INMV) && (when & (WHEN_VIINP|WHEN_VIREP)))
01016 {
01017 strcat(tmpblk.c, "visual ");
01018 }
01019 # endif
01020 safequote(scan->cooked);
01021 strcat(tmpblk.c, "\n");
01022 twrite(fd, tmpblk.c, strlen(tmpblk.c));
01023 }
01024 }
01025 }
01026 #endif