00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "config.h"
00016 #include "ctype.h"
00017 #include "vi.h"
00018
00019
00020 #ifndef NO_DIGRAPH
00021 static struct _DIG
00022 {
00023 struct _DIG *next;
00024 char key1;
00025 char key2;
00026 char dig;
00027 char save;
00028 } *digs;
00029
00030 char digraph(key1, key2)
00031 char key1;
00032 char key2;
00033 {
00034 int newkey;
00035 REG struct _DIG *dp;
00036
00037
00038 if (!*o_digraph)
00039 {
00040 return key2;
00041 }
00042
00043
00044 newkey = key2;
00045
00046
00047 if (key1 > key2)
00048 {
00049 key2 = key1;
00050 key1 = newkey;
00051 }
00052
00053
00054 for (dp = digs;
00055 dp && (dp->key1 != key1 || dp->key2 != key2);
00056 dp = dp->next)
00057 {
00058 }
00059
00060
00061 if (!dp)
00062 {
00063 return newkey;
00064 }
00065
00066
00067 return dp->dig;
00068 }
00069
00070
00071 void do_digraph(bang, extra)
00072 int bang;
00073 char extra[];
00074 {
00075 int dig;
00076 REG struct _DIG *dp;
00077 struct _DIG *prev;
00078 static int user_defined = FALSE;
00079 char listbuf[8];
00080
00081
00082 if (!extra)
00083 {
00084 user_defined = TRUE;
00085 return;
00086 }
00087
00088
00089 if (*extra < ' ')
00090 {
00091 listbuf[0] = listbuf[1] = listbuf[2] = listbuf[5] = ' ';
00092 listbuf[7] = '\0';
00093 for (dig = 0, dp = digs; dp; dp = dp->next)
00094 {
00095 if (dp->save || bang)
00096 {
00097 dig += 7;
00098 if (dig >= COLS)
00099 {
00100 addch('\n');
00101 exrefresh();
00102 dig = 7;
00103 }
00104 listbuf[3] = dp->key1;
00105 listbuf[4] = dp->key2;
00106 listbuf[6] = dp->dig;
00107 qaddstr(listbuf);
00108 }
00109 }
00110 addch('\n');
00111 exrefresh();
00112 return;
00113 }
00114
00115
00116 if (!extra[1])
00117 {
00118 msg("Digraphs must be composed of two characters");
00119 return;
00120 }
00121
00122
00123 if (extra[0] > extra[1])
00124 {
00125 dig = extra[0];
00126 extra[0] = extra[1];
00127 extra[1] = dig;
00128 }
00129
00130
00131 for (dig = 2; extra[dig] == ' ' || extra[dig] == '\t'; dig++)
00132 {
00133 }
00134 dig = extra[dig];
00135 if (!bang && dig)
00136 {
00137 dig |= 0x80;
00138 }
00139
00140
00141 for (prev = (struct _DIG *)0, dp = digs;
00142 dp && (dp->key1 != extra[0] || dp->key2 != extra[1]);
00143 prev = dp, dp = dp->next)
00144 {
00145 }
00146
00147
00148 if (!dig)
00149 {
00150 if (!dp)
00151 {
00152 #ifndef CRUNCH
00153 msg("%c%c not a digraph", extra[0], extra[1]);
00154 #endif
00155 return;
00156 }
00157 if (prev)
00158 prev->next = dp->next;
00159 else
00160 digs = dp->next;
00161 free(dp);
00162 return;
00163 }
00164
00165
00166 if (dig && !dp)
00167 {
00168 dp = (struct _DIG *)malloc(sizeof *dp);
00169 if (!dp)
00170 {
00171 msg("Out of space in the digraph table");
00172 return;
00173 }
00174 if (prev)
00175 prev->next = dp;
00176 else
00177 digs = dp;
00178 dp->next = (struct _DIG *)0;
00179 }
00180
00181
00182 dp->key1 = extra[0];
00183 dp->key2 = extra[1];
00184 dp->dig = dig;
00185 dp->save = user_defined;
00186 }
00187
00188 # ifndef NO_MKEXRC
00189 void savedigs(fd)
00190 int fd;
00191 {
00192 static char buf[] = "digraph! XX Y\n";
00193 REG struct _DIG *dp;
00194
00195 for (dp = digs; dp; dp = dp->next)
00196 {
00197 if (dp->save)
00198 {
00199 buf[9] = dp->key1;
00200 buf[10] = dp->key2;
00201 buf[12] = dp->dig;
00202 write(fd, buf, (unsigned)14);
00203 }
00204 }
00205 }
00206 # endif
00207 #endif
00208
00209
00210
00211
00212
00213
00214 MARK input(from, to, when, above)
00215 MARK from;
00216 MARK to;
00217 int when;
00218 int above;
00219 {
00220 char key[2];
00221 char *build;
00222 char *scan;
00223 MARK m;
00224 #ifndef NO_EXTENSIONS
00225 int quit = FALSE;
00226 int inchg;
00227 #endif
00228
00229 #ifdef DEBUG
00230
00231 if (from > to)
00232 {
00233 msg("ERROR: input(%ld:%d, %ld:%d)",
00234 markline(from), markidx(from),
00235 markline(to), markidx(to));
00236 return MARK_UNSET;
00237 }
00238 #endif
00239
00240 key[1] = 0;
00241
00242
00243
00244 if (from != to)
00245 {
00246 cut(from, to);
00247 }
00248
00249
00250 if (doingdot)
00251 {
00252 ChangeText
00253 {
00254
00255 if (from != to)
00256 {
00257 delete(from, to);
00258 }
00259
00260
00261 cutname('.');
00262 cursor = paste(from, FALSE, TRUE) + 1L;
00263 }
00264 }
00265 else
00266 {
00267
00268 #ifndef NO_EXTENSIONS
00269 inchg = TRUE;
00270 #endif
00271
00272
00273 if (from != to && markline(from) == markline(to))
00274 {
00275
00276 change(to - 1, to, "$");
00277 }
00278 else
00279 {
00280
00281 if (from != to)
00282 {
00283 delete(from, to);
00284 }
00285 to = from;
00286 }
00287
00288
00289 cursor = from;
00290 m = (above ? (cursor + BLKSIZE) : (cursor - BLKSIZE));
00291 if (*o_autoindent && markidx(m) == 0
00292 && markline(m) >= 1L && markline(m) <= nlines)
00293 {
00294
00295 pfetch(markline(cursor));
00296 if (plen == 0)
00297 {
00298
00299 pfetch(markline(m));
00300 for (scan = ptext, build = tmpblk.c;
00301 *scan == ' ' || *scan == '\t';
00302 )
00303 {
00304 *build++ = *scan++;
00305 }
00306 if (build > tmpblk.c)
00307 {
00308 *build = '\0';
00309 add(cursor, tmpblk.c);
00310 cursor += (build - tmpblk.c);
00311 if (cursor > to)
00312 to = cursor;
00313 }
00314 }
00315 }
00316
00317
00318 for (;;)
00319 {
00320
00321 redraw(cursor, TRUE);
00322 #ifdef DEBUG2
00323 msg("cursor=%ld.%d, to=%ld.%d",
00324 markline(cursor), markidx(cursor),
00325 markline(to), markidx(to));
00326 #endif
00327 #ifndef NO_ABBR
00328 pfetch(markline(cursor));
00329 build = ptext;
00330 if (pline == markline(from))
00331 build += markidx(from);
00332 for (scan = ptext + markidx(cursor); --scan >= build && isalnum(*scan); )
00333 {
00334 }
00335 scan++;
00336 key[0] = getabkey(when, scan, (int)(ptext + markidx(cursor) - scan));
00337 #else
00338 key[0] = getkey(when);
00339 #endif
00340 #ifndef NO_VISIBLE
00341 if (key[0] != '\0' && V_from != MARK_UNSET)
00342 {
00343 msg("Can't modify text during a selection");
00344 beep();
00345 continue;
00346 }
00347 #endif
00348
00349 #ifndef NO_EXTENSIONS
00350 if (key[0] == ctrl('O'))
00351 {
00352 if (inchg)
00353 {
00354 if (cursor < to)
00355 {
00356 delete(cursor, to);
00357 redraw(cursor, TRUE);
00358 }
00359 afterdo();
00360 inchg = FALSE;
00361 }
00362 }
00363 else if (key[0] != ctrl('['))
00364 {
00365 if (!inchg)
00366 {
00367 beforedo(FALSE);
00368 inchg = TRUE;
00369 }
00370 }
00371 #endif
00372
00373 #ifndef CRUNCH
00374
00375
00376
00377
00378 if (*o_wrapmargin != 0)
00379 {
00380 pfetch(markline(cursor));
00381 if (idx2col(cursor, ptext, TRUE) > COLS - (*o_wrapmargin & 0xff))
00382 {
00383 build = tmpblk.c;
00384 *build++ = '\n';
00385 if (*o_autoindent)
00386 {
00387
00388 for (scan = ptext; *scan == ' ' || *scan == '\t'; )
00389 {
00390 *build++ = *scan++;
00391 }
00392 }
00393 *build = '\0';
00394
00395 scan = ptext + plen;
00396 m = cursor & ~(BLKSIZE - 1);
00397 while (ptext < scan)
00398 {
00399 scan--;
00400 if (*scan != ' ' && *scan != '\t')
00401 continue;
00402
00403
00404 change(m + (scan - ptext), m + (scan - ptext) + 1, tmpblk.c);
00405 cursor = (cursor & ~(BLKSIZE - 1))
00406 + BLKSIZE
00407 + strlen(tmpblk.c) - 1
00408 + plen - (scan - ptext) - 1;
00409
00410
00411 pfetch(markline(m));
00412 scan = ptext + plen;
00413 while (ptext < scan)
00414 {
00415 scan--;
00416 if (*scan != ' ' && *scan != '\t')
00417 break;
00418 }
00419 delete(m + (scan-ptext) + 1, m + plen);
00420
00421 break;
00422 }
00423 }
00424 }
00425 #endif
00426
00427
00428 switch (*key)
00429 {
00430 #ifndef NO_EXTENSIONS
00431 case ctrl('O'):
00432 *key = getkey(0);
00433 switch (*key)
00434 {
00435 case 'h': m = m_left(cursor, 0L); break;
00436 case 'j':
00437 case 'k': m = m_updnto(cursor, 0L, *key); break;
00438 case 'l': m = cursor + 1; break;
00439 case 'B':
00440 case 'b': m = m_bword(cursor, 0L, *key); break;
00441 case 'W':
00442 case 'w': m = m_fword(cursor, 0L, *key, '\0'); break;
00443 case '^': m = m_front(cursor, 0L); break;
00444 case '$': m = m_rear(cursor, 0L); break;
00445 case ctrl('B'):
00446 case ctrl('F'):
00447 m = m_scroll(cursor, 0L, *key); break;
00448 case 'x':
00449 #ifndef NO_VISIBLE
00450 if (V_from)
00451 beep();
00452 else
00453 #endif
00454 ChangeText
00455 {
00456 m = v_xchar(cursor, 0L, 'x');
00457 }
00458 break;
00459 case 'i': m = to = from = cursor;
00460 when = WHEN_VIINP + WHEN_VIREP - when;
00461 break;
00462 case 'K':
00463 pfetch(markline(cursor));
00464 changes++;
00465 ptext[markidx(cursor)] = 0;
00466 for (scan = ptext + markidx(cursor) - 1;
00467 scan >= ptext && isalnum(*scan);
00468 scan--)
00469 {
00470 }
00471 scan++;
00472 m = (*scan ? v_keyword(scan, cursor, 0L) : cursor);
00473 break;
00474
00475 # ifndef NO_VISIBLE
00476 case 'v':
00477 case 'V':
00478 if (V_from)
00479 V_from = MARK_UNSET;
00480 else
00481 V_from = cursor;
00482 m = from = to = cursor;
00483 V_linemd = (*key == 'V');
00484 break;
00485
00486 case 'd':
00487 case 'y':
00488 case '\\':
00489
00490 if (!V_from)
00491 {
00492 msg("You must mark the text first");
00493 beep();
00494 break;
00495 }
00496
00497
00498 if (V_from < cursor)
00499 {
00500 from = V_from;
00501 to = cursor;
00502 }
00503 else
00504 {
00505 from = cursor;
00506 to = V_from;
00507 }
00508
00509
00510 V_from = MARK_UNSET;
00511
00512 if (V_linemd)
00513 {
00514
00515 from &= ~(BLKSIZE - 1);
00516 to |= (BLKSIZE - 1);
00517 }
00518 else
00519 {
00520
00521
00522
00523
00524 pfetch(markline(to));
00525 if (markidx(to) == plen)
00526 to |= (BLKSIZE - 1);
00527 }
00528 to++;
00529
00530 switch (*key)
00531 {
00532 case 'y':
00533 cut(from, to);
00534 break;
00535
00536 case 'd':
00537 ChangeText
00538 {
00539 cut(from, to);
00540 delete(from, to);
00541 }
00542 cursor = from;
00543 break;
00544
00545 #ifndef NO_POPUP
00546 case '\\':
00547 ChangeText
00548 {
00549 cursor = v_popup(from, to);
00550 }
00551 break;
00552 #endif
00553 }
00554 m = from = to = cursor;
00555 break;
00556
00557 case 'p':
00558 case 'P':
00559 V_from = MARK_UNSET;
00560 ChangeText
00561 {
00562 m = from = to = cursor = paste(cursor, (*key == 'p'), FALSE);
00563 }
00564 break;
00565 # endif
00566 default: m = MARK_UNSET;
00567 }
00568
00569
00570 if (m != cursor)
00571 {
00572 m = adjmove(cursor, m, (*key == 'j' || *key == 'k' ? 0x20 : 0));
00573 if (*key == '$' || (*key == 'l' && m <= cursor))
00574 {
00575 m++;
00576 }
00577 }
00578
00579
00580 if (m == MARK_UNSET)
00581 {
00582 beep();
00583 }
00584 else
00585 {
00586 from = to = cursor = m;
00587 }
00588 break;
00589
00590 case ctrl('Z'):
00591 if (getkey(0) == ctrl('Z'))
00592 {
00593 quit = TRUE;
00594 goto BreakBreak;
00595 }
00596 break;
00597 #endif
00598
00599 case ctrl('['):
00600
00601 if (*o_autoindent)
00602 {
00603 pfetch(markline(cursor));
00604 for (scan = ptext; isspace(*scan); scan++)
00605 {
00606 }
00607 if (scan > ptext && !*scan)
00608 {
00609 cursor &= ~(BLKSIZE - 1L);
00610 if (to < cursor + plen)
00611 {
00612 to = cursor + plen;
00613 }
00614 }
00615 }
00616 goto BreakBreak;
00617
00618 case ctrl('U'):
00619 if (markline(cursor) == markline(from))
00620 {
00621 cursor = from;
00622 }
00623 else
00624 {
00625 cursor &= ~(BLKSIZE - 1);
00626 }
00627 break;
00628
00629 case ctrl('D'):
00630 case ctrl('T'):
00631 if (to > cursor)
00632 {
00633 delete(cursor, to);
00634 }
00635 mark[27] = cursor;
00636 cmd_shift(cursor, cursor, *key == ctrl('D') ? CMD_SHIFTL : CMD_SHIFTR, TRUE, "");
00637 if (mark[27])
00638 {
00639 cursor = mark[27];
00640 }
00641 else
00642 {
00643 cursor = m_front(cursor, 0L);
00644 }
00645 to = cursor;
00646 break;
00647
00648 case '\b':
00649 if (cursor <= from)
00650 {
00651 beep();
00652 }
00653 else if (markidx(cursor) == 0)
00654 {
00655 cursor -= BLKSIZE;
00656 pfetch(markline(cursor));
00657 cursor += plen;
00658 }
00659 else
00660 {
00661 cursor--;
00662 }
00663 break;
00664
00665 case ctrl('W'):
00666 m = m_bword(cursor, 1L, 'b');
00667 if (markline(m) == markline(cursor) && m >= from)
00668 {
00669 cursor = m;
00670 if (from > cursor)
00671 {
00672 from = cursor;
00673 }
00674 }
00675 else
00676 {
00677 beep();
00678 }
00679 break;
00680
00681 case '\n':
00682 #if OSK
00683 case '\l':
00684 #else
00685 case '\r':
00686 #endif
00687 build = tmpblk.c;
00688 *build++ = '\n';
00689 if (*o_autoindent)
00690 {
00691
00692 pfetch(markline(cursor));
00693 for (scan = ptext; *scan == ' ' || *scan == '\t'; )
00694 {
00695 *build++ = *scan++;
00696 }
00697
00698
00699 if ((scan - ptext) >= markidx(cursor) && plen > 0)
00700 {
00701 to = cursor &= ~(BLKSIZE - 1);
00702 delete(cursor, cursor + plen);
00703 }
00704 }
00705 *build = 0;
00706 if (cursor >= to && when != WHEN_VIREP)
00707 {
00708 add(cursor, tmpblk.c);
00709 }
00710 else
00711 {
00712 change(cursor, to, tmpblk.c);
00713 }
00714 redraw(cursor, TRUE);
00715 to = cursor = (cursor & ~(BLKSIZE - 1))
00716 + BLKSIZE
00717 + (int)(build - tmpblk.c) - 1;
00718 break;
00719
00720 case ctrl('A'):
00721 case ctrl('P'):
00722 if (cursor < to)
00723 {
00724 delete(cursor, to);
00725 }
00726 if (*key == ctrl('A'))
00727 {
00728 cutname('.');
00729 }
00730 to = cursor = paste(cursor, FALSE, TRUE) + 1L;
00731 break;
00732
00733 case ctrl('V'):
00734 if (cursor >= to && when != WHEN_VIREP)
00735 {
00736 add(cursor, "^");
00737 }
00738 else
00739 {
00740 change(cursor, to, "^");
00741 to = cursor + 1;
00742 }
00743 redraw(cursor, TRUE);
00744 *key = getkey(0);
00745 if (*key == '\n')
00746 {
00747
00748 #if OSK
00749 *key = '\l';
00750 #else
00751 *key = '\r';
00752 #endif
00753 }
00754 change(cursor, cursor + 1, key);
00755 cursor++;
00756 if (cursor > to)
00757 {
00758 to = cursor;
00759 }
00760 break;
00761
00762 case ctrl('L'):
00763 case ctrl('R'):
00764 redraw(MARK_UNSET, FALSE);
00765 break;
00766
00767 default:
00768 if (cursor >= to && when != WHEN_VIREP)
00769 {
00770 add(cursor, key);
00771 cursor++;
00772 to = cursor;
00773 }
00774 else
00775 {
00776 pfetch(markline(cursor));
00777 if (markidx(cursor) == plen)
00778 {
00779 add(cursor, key);
00780 }
00781 else
00782 {
00783 #ifndef NO_DIGRAPH
00784 *key = digraph(ptext[markidx(cursor)], *key);
00785 #endif
00786 change(cursor, cursor + 1, key);
00787 }
00788 cursor++;
00789 }
00790 #ifndef NO_SHOWMATCH
00791
00792 if (*o_showmatch && strchr(")}]", *key))
00793 {
00794 redraw(cursor, TRUE);
00795 m = m_match(cursor - 1, 0L);
00796 if (markline(m) >= topline
00797 && markline(m) <= botline)
00798 {
00799 redraw(m, TRUE);
00800 refresh();
00801 sleep(1);
00802 }
00803 }
00804 #endif
00805 }
00806 }
00807 BreakBreak:;
00808
00809 if (cursor < to)
00810 {
00811 #ifndef NO_EXTENSIONS
00812
00813 if (!inchg)
00814 {
00815 beforedo(FALSE);
00816 inchg = TRUE;
00817 }
00818 #endif
00819 delete(cursor, to);
00820 }
00821
00822 }
00823
00824
00825 if (!doingdot)
00826 {
00827 blksync();
00828 cutname('.');
00829 cut(from, cursor);
00830 }
00831
00832
00833 if (markidx(cursor) != 0)
00834 {
00835 cursor--;
00836 }
00837 redraw(cursor, FALSE);
00838
00839 #ifndef NO_EXTENSIONS
00840 if (quit)
00841 {
00842
00843 abortdo();
00844
00845
00846 cursor = v_xit(cursor, 0L, 'Z');
00847 }
00848 #endif
00849
00850 rptlines = 0L;
00851 return cursor;
00852 }