1 /* $MirOS: contrib/code/jupp/uedit.c,v 1.17 2017/03/19 19:19:51 tg Exp $ */
3 * Basic user edit functions
5 * (C) 1992 Joseph H. Allen
7 * This file is part of JOE (Joe's Own Editor)
15 #ifdef HAVE_BSD_STRING_H
16 #include <bsd/string.h>
37 int pgamnt = -1; /* No. of PgUp/PgDn lines to keep */
39 /******** i don't like global var ******/
42 * Move cursor to beginning of line
44 int u_goto_bol(BW *bw)
47 pbkwd(bw->cursor,bw->cursor->byte%16);
49 p_goto_bol(bw->cursor);
55 * Move cursor to first non-whitespace character, unless it is
56 * already there, in which case move it to beginning of line
63 return u_goto_bol(bw);
68 if (bw->o.indentfirst) {
69 if ((bw->o.smarthome) && (piscol(p) > pisindent(p))) {
71 while (joe_isblank(p->b->o.charmap,brc(p)))
76 if (bw->o.smarthome && piscol(p)==0 && pisindent(p)) {
77 while (joe_isblank(p->b->o.charmap,brc(p)))
89 * Move cursor to end of line
91 int u_goto_eol(BW *bw)
94 if (bw->cursor->byte + 15 - bw->cursor->byte%16 > bw->b->eof->byte)
95 pset(bw->cursor,bw->b->eof);
97 pfwrd(bw->cursor, 15 - bw->cursor->byte%16);
99 p_goto_eol(bw->cursor);
104 * Move cursor to beginning of file
106 int u_goto_bof(BW *bw)
108 p_goto_bof(bw->cursor);
113 * Move cursor to end of file
115 int u_goto_eof(BW *bw)
117 p_goto_eof(bw->cursor);
124 int u_goto_left(BW *bw)
127 if (prgetb(bw->cursor) != NO_MORE_DATA) {
134 if (bw->cursor->xcol) {
136 pcol(bw->cursor,bw->cursor->xcol);
140 /* Have to do ECHKXCOL here because of picture mode */
141 if (bw->cursor->xcol != piscol(bw->cursor)) {
142 bw->cursor->xcol = piscol(bw->cursor);
144 } else if (prgetc(bw->cursor) != NO_MORE_DATA) {
145 bw->cursor->xcol = piscol(bw->cursor);
155 int u_goto_right(BW *bw)
158 if (pgetb(bw->cursor) != NO_MORE_DATA) {
166 pcol(bw->cursor,bw->cursor->xcol);
170 if (pgetc(bw->cursor) != NO_MORE_DATA) {
171 bw->cursor->xcol = piscol(bw->cursor);
176 /* Have to do EFIXXCOL here because of picture mode */
177 if (bw->cursor->xcol != piscol(bw->cursor))
178 bw->cursor->xcol = piscol(bw->cursor);
184 * Move cursor to beginning of previous word or if there isn't
185 * previous word then go to beginning of the file
187 * WORD is a sequence non-white-space characters
189 int u_goto_prev(BW *bw)
191 P *p = pdup(bw->cursor);
192 struct charmap *map=bw->b->o.charmap;
195 if (joe_isalnum_(map,c)) {
196 while (joe_isalnum_(map,(c=prgetc(p))))
198 if (c != NO_MORE_DATA)
200 } else if (joe_isspace(map,c) || joe_ispunct(map,c)) {
201 while ((c=prgetc(p)), (joe_isspace(map,c) || joe_ispunct(map,c)))
203 while(joe_isalnum_(map,(c=prgetc(p))))
205 if (c != NO_MORE_DATA)
209 if (p->byte == bw->cursor->byte) {
220 * Move cursor to end of next word or if there isn't
221 * next word then go to end of the file
223 * WORD is a sequence non-white-space characters
225 int u_goto_next(BW *bw)
227 P *p = pdup(bw->cursor);
228 struct charmap *map=bw->b->o.charmap;
232 if (joe_isalnum_(map,c)) {
234 while (joe_isalnum_(map,(c = brch(p))))
236 } else if (joe_isspace(map,c) || joe_ispunct(map,c)) {
237 while (joe_isspace(map, (c = brch(p))) || joe_ispunct(map,c))
239 while (joe_isalnum_(map,(c = brch(p)))) {
253 while (joe_isblank(p->b->o.charmap,brch(p)))
258 static int pisedge(P *p)
269 if (q->byte == p->byte)
271 if (joe_isblank(p->b->o.charmap,(c = brch(p)))) {
273 if (joe_isblank(p->b->o.charmap,prgetc(q)))
289 if (prgetc(q) == ' ')
304 if (prgetc(bw->cursor) == NO_MORE_DATA)
306 while (pisedge(bw->cursor) != -1)
313 if (pgetc(bw->cursor) == NO_MORE_DATA)
315 while (pisedge(bw->cursor) != 1)
320 /* Move cursor to matching delimiter */
323 utomatch_i(BW *bw, int dir)
326 int c; /* character under cursor */
327 int f; /* character to find */
329 int cnt = 0; /* delimiter depth */
331 switch (c = brch(bw->cursor)) {
373 p = pdup(bw->cursor);
375 while ((d = pgetc(p)) != NO_MORE_DATA) {
376 if (d == f && f != c && !--cnt) {
386 while ((d = prgetc(p)) != NO_MORE_DATA) {
387 if (d == f && !cnt--)
393 if (/* CONSTCOND */ 0) {
398 return ((d == NO_MORE_DATA) ? -1 : 0);
403 return (utomatch_i(bw, 1));
408 return (utomatch_i(bw, -1));
416 if (bw->cursor->byte<16)
419 pbkwd(bw->cursor, 16);
423 if (bw->cursor->line) {
425 pcol(bw->cursor, bw->cursor->xcol);
431 /* Move cursor down */
436 if (bw->cursor->byte+16 <= bw->b->eof->byte) {
437 pfwrd(bw->cursor, 16);
439 } else if (bw->cursor->byte != bw->b->eof->byte) {
440 pset(bw->cursor, bw->b->eof);
446 if (bw->cursor->line != bw->b->eof->line) {
448 pcol(bw->cursor, bw->cursor->xcol);
450 } else if(bw->o.picture) {
451 p_goto_eol(bw->cursor);
452 binsc(bw->cursor,'\n');
454 pcol(bw->cursor, bw->cursor->xcol);
460 /* Move cursor to top of window */
464 long col = bw->cursor->xcol;
466 pset(bw->cursor, bw->top);
467 pcol(bw->cursor, col);
468 bw->cursor->xcol = col;
472 /* Move cursor to bottom of window */
476 long col = bw->cursor->xcol;
478 pline(bw->cursor, bw->top->line + bw->h - 1);
479 pcol(bw->cursor, col);
480 bw->cursor->xcol = col;
484 /* Scroll buffer window up n lines
485 * If beginning of file is close, scrolls as much as it can
486 * If beginning of file is on-screen, cursor jumps to beginning of file
488 * If flg is set: cursor stays fixed relative to screen edge
489 * If flg is clr: cursor stays fixed on the buffer line
492 void scrup(BW *bw, int n, int flg)
498 /* Decide number of lines we're really going to scroll */
501 if (bw->top->byte/16 >= n)
502 scrollamnt = cursoramnt = n;
503 else if (bw->top->byte/16)
504 scrollamnt = cursoramnt = bw->top->byte/16;
506 cursoramnt = bw->cursor->byte/16;
507 else if (bw->cursor->byte/16 >= n)
510 if (bw->top->line >= n)
511 scrollamnt = cursoramnt = n;
512 else if (bw->top->line)
513 scrollamnt = cursoramnt = bw->top->line;
515 cursoramnt = bw->cursor->line;
516 else if (bw->cursor->line >= n)
521 /* Move top-of-window pointer */
522 pbkwd(bw->top,scrollamnt*16);
524 pbkwd(bw->cursor,cursoramnt*16);
525 /* If window is on the screen, give (buffered) scrolling command */
526 if (bw->parent->y != -1)
527 nscrldn(bw->parent->t->t, bw->y, bw->y + bw->h, scrollamnt);
529 /* Move top-of-window pointer */
530 for (x = 0; x != scrollamnt; ++x)
535 for (x = 0; x != cursoramnt; ++x)
537 p_goto_bol(bw->cursor);
538 pcol(bw->cursor, bw->cursor->xcol);
540 /* If window is on the screen, give (buffered) scrolling command */
541 if (bw->parent->y != -1)
542 nscrldn(bw->parent->t->t, bw->y, bw->y + bw->h, scrollamnt);
546 /* Scroll buffer window down n lines
547 * If end of file is close, scrolls as much as possible
548 * If end of file is on-screen, cursor jumps to end of file
550 * If flg is set: cursor stays fixed relative to screen edge
551 * If flg is clr: cursor stays fixed on the buffer line
554 void scrdn(BW *bw, int n, int flg)
560 /* How much we're really going to scroll... */
562 if (bw->top->b->eof->byte/16 < bw->top->byte/16 + bw->h) {
563 cursoramnt = bw->top->b->eof->byte/16 - bw->cursor->byte/16;
564 if (!flg && cursoramnt > n)
566 } else if (bw->top->b->eof->byte/16 - (bw->top->byte/16 + bw->h) >= n)
567 cursoramnt = scrollamnt = n;
569 cursoramnt = scrollamnt = bw->top->b->eof->byte/16 - (bw->top->byte/16 + bw->h) + 1;
571 if (bw->top->b->eof->line < bw->top->line + bw->h) {
572 cursoramnt = bw->top->b->eof->line - bw->cursor->line;
573 if (!flg && cursoramnt > n)
575 } else if (bw->top->b->eof->line - (bw->top->line + bw->h) >= n)
576 cursoramnt = scrollamnt = n;
578 cursoramnt = scrollamnt = bw->top->b->eof->line - (bw->top->line + bw->h) + 1;
582 /* Move top-of-window pointer */
583 pfwrd(bw->top,16*scrollamnt);
585 pfwrd(bw->cursor,16*cursoramnt);
586 /* If window is on screen, give (buffered) scrolling command to terminal */
587 if (bw->parent->y != -1)
588 nscrlup(bw->parent->t->t, bw->y, bw->y + bw->h, scrollamnt);
590 /* Move top-of-window pointer */
591 for (x = 0; x != scrollamnt; ++x)
595 for (x = 0; x != cursoramnt; ++x)
597 pcol(bw->cursor, bw->cursor->xcol);
599 /* If window is on screen, give (buffered) scrolling command to terminal */
600 if (bw->parent->y != -1)
601 nscrlup(bw->parent->t->t, bw->y, bw->y + bw->h, scrollamnt);
609 bw = (BW *) bw->parent->main->object;
610 if (bw->o.hex ? bw->cursor->byte < 16 : !bw->cursor->line)
613 scrup(bw, bw->h / 2 + bw->h % 2, 1);
614 else if (pgamnt < bw->h)
615 scrup(bw, bw->h - pgamnt, 1);
625 bw = (BW *) bw->parent->main->object;
626 if (bw->o.hex ? bw->cursor->byte/16 == bw->b->eof->byte/16 : bw->cursor->line == bw->b->eof->line)
629 scrdn(bw, bw->h / 2 + bw->h % 2, 1);
630 else if (pgamnt < bw->h)
631 scrdn(bw, bw->h - pgamnt, 1);
637 /* Scroll by a single line. The cursor moves with the scroll */
641 bw = (BW *) bw->parent->main->object;
642 if (bw->o.hex ? bw->top->byte/16 : bw->top->line) {
643 if (bw->o.hex ? bw->top->byte/16 + bw->h -1 != bw->cursor->byte/16 : bw->top->line + bw->h - 1 != bw->cursor->line)
653 bw = (BW *) bw->parent->main->object;
654 if (bw->o.hex ? bw->top->line/16 + bw->h <= bw->top->b->eof->byte/16 : bw->top->line + bw->h <= bw->top->b->eof->line) {
655 if (bw->o.hex ? bw->top->byte/16 != bw->cursor->byte/16 : bw->top->line != bw->cursor->line)
663 /* Move cursor to specified line number */
665 static B *linehist = NULL; /* History of previously entered line numbers */
667 static int doline(BW *bw, unsigned char *s, void *object, int *notify)
669 long num = calc(bw, s);
674 if (num >= 1 && !merrf) {
677 if (num > bw->b->eof->line)
678 num = bw->b->eof->line + 1;
679 pline(bw->cursor, num - 1), bw->cursor->xcol = piscol(bw->cursor);
686 msgnw(bw->parent, merrt);
688 msgnw(bw->parent, US "Invalid line number");
695 if (wmkpw(bw->parent, US "Go to line (^C to abort): ", &linehist, doline, NULL, NULL, NULL, NULL, NULL, locale_map))
701 /* Move cursor to specified column number */
703 static B *colhist = NULL; /* History of previously entered column numbers */
705 static int docol(BW *bw, unsigned char *s, void *object, int *notify)
707 long num = calc(bw, s);
712 if (num >= 1 && !merrf) {
715 pcol(bw->cursor, num - 1), bw->cursor->xcol = piscol(bw->cursor);
722 msgnw(bw->parent, merrt);
724 msgnw(bw->parent, US "Invalid column number");
731 if (wmkpw(bw->parent, US "Go to column (^C to abort): ", &colhist, docol, NULL, NULL, NULL, NULL, NULL, locale_map))
737 /* Move cursor to specified byte number */
739 static B *bytehist = NULL; /* History of previously entered byte numbers */
741 static int dobyte(BW *bw, unsigned char *s, void *object, int *notify)
743 long num = calc(bw, s);
748 if (num >= 0 && !merrf) {
751 pgoto(bw->cursor, num), bw->cursor->xcol = piscol(bw->cursor);
758 msgnw(bw->parent, merrt);
760 msgnw(bw->parent, US "Invalid byte number");
767 if (wmkpw(bw->parent, US "Go to byte (^C to abort): ", &bytehist, dobyte, NULL, NULL, NULL, NULL, NULL, locale_map))
773 /* Delete character under cursor
774 * or write ^D to process if we're at end of file in a shell window
781 if (piseof(bw->cursor))
783 pgetc(p = pdup(bw->cursor));
791 int ubacks(BW *bw, int k)
793 /* Don't backspace when at beginning of line in prompt windows */
794 if (bw->parent->watom->what == TYPETW || !pisbol(bw->cursor)) {
801 if (pisbof(bw->cursor))
804 /* Indentation point of this line */
805 indent = pisindent(bw->cursor);
807 /* Column position of cursor */
808 col = piscol(bw->cursor);
810 /* Indentation step in columns */
811 if (bw->o.indentc=='\t')
816 indwid = (bw->o.istep*wid);
818 /* Smart backspace when: cursor is at indentation point, indentation point
819 is a multiple of indentation width, we're not at beginning of line,
820 'smarthome' option is enabled, and indentation is purely made out of
821 indent characters (or purify indents is enabled). */
823 /* Ignore purify for backspace */
824 if (col == indent && (col%indwid)==0 && col!=0 && bw->o.smartbacks) {
827 /* Delete all indentation */
828 p = pdup(bw->cursor);
833 /* Indent to new position */
834 pfill(bw->cursor,col-indwid,bw->o.indentc);
835 } else if (col<indent && !pisbol(bw->cursor) && bw->o.smartbacks) {
836 /* We're before indent point: delete indwid worth of space but do not
837 cross line boundary. We could probably replace the above with this. */
839 P *p = pdup(bw->cursor);
841 c = prgetc(bw->cursor);
842 if(c=='\t') cw += bw->o.tab;
845 } while(!pisbol(bw->cursor) && cw<indwid);
848 /* Regular backspace */
849 P *p = pdup(bw->cursor);
850 if ((c = prgetc(bw->cursor)) != NO_MORE_DATA)
851 if (!bw->o.overtype || c == '\t' || pisbol(p) || piseol(p))
861 * Delete sequence of characters (alphabetic, numeric) or (white-space)
862 * if cursor is on the white-space it will delete all white-spaces
863 * until alphanumeric character
864 * if cursor is on the alphanumeric it will delete all alphanumeric
865 * characters until character that is not alphanumeric
867 int u_word_delete(BW *bw)
869 P *p = pdup(bw->cursor);
870 struct charmap *map=bw->b->o.charmap;
873 if (joe_isalnum_(map,c))
874 while (joe_isalnum_(map,(c = brch(p))))
876 else if (joe_isspace(map,c))
877 while (joe_isspace(map,(c = brch(p))))
882 if (p->byte == bw->cursor->byte) {
891 /* Delete from cursor to beginning of word it's in or immediately after,
892 * to start of whitespace, or a single character
897 P *p = pdup(bw->cursor);
898 int c = prgetc(bw->cursor);
899 struct charmap *map=bw->b->o.charmap;
901 if (joe_isalnum_(map,c)) {
902 while (joe_isalnum_(map,(c = prgetc(bw->cursor))))
904 if (c != NO_MORE_DATA)
906 } else if (joe_isspace(map,c)) {
907 while (joe_isspace(map,(c = prgetc(bw->cursor))))
909 if (c != NO_MORE_DATA)
912 if (bw->cursor->byte == p->byte) {
921 /* Delete from cursor to end of line, or if there's nothing to delete,
922 * delete the line-break
927 P *p = p_goto_eol(pdup(bw->cursor));
929 if (bw->cursor->byte == p->byte) {
938 /* Delete to beginning of line, or if there's nothing to delete,
939 * delete the line-break
944 P *p = p_goto_bol(pdup(bw->cursor));
946 if (p->byte == bw->cursor->byte) {
948 return ubacks(bw, 8); /* The 8 goes to the process if we're at EOF of shell window */
955 /* Delete entire line */
959 P *p = pdup(bw->cursor);
961 p_goto_bol(bw->cursor);
963 if (bw->cursor->byte == p->byte) {
976 binsc(bw->cursor, ' ');
980 /* Move p backwards to first non-blank line and return its indentation */
982 int find_indent(P *p)
985 for (x=0; x != 10; ++x) {
986 if (!pprevl(p)) return -1;
988 if (!pisblank(p)) break;
996 /* Type a character into the buffer (deal with left margin, overtype mode and
997 * word-wrap), if cursor is at end of shell window buffer, just send character
1001 struct utf8_sm utype_utf8_sm;
1003 int utypebw_raw(BW *bw, int k, int no_decode)
1005 struct charmap *map=bw->b->o.charmap;
1007 /* Hex mode overtype is real simple */
1008 if (bw->o.hex && bw->o.overtype) {
1010 unsigned char c = k;
1011 binsm(bw->cursor, &c, 1);
1013 if (piseof(bw->cursor))
1015 pgetb(p = pdup(bw->cursor));
1016 bdel(bw->cursor, p);
1021 if (k == '\t' && bw->o.overtype && !piseol(bw->cursor)) { /* TAB in overtype mode is supposed to be just cursor motion */
1022 int col = bw->cursor->xcol; /* Current cursor column */
1023 col = col + bw->o.tab - (col%bw->o.tab);/* Move to next tab stop */
1024 pcol(bw->cursor,col); /* Try to position cursor there */
1025 if (!bw->o.picture && piseol(bw->cursor) && piscol(bw->cursor)<col) { /* We moved past end of line, insert a tab (unless in picture mode) */
1027 pfill(bw->cursor,col,' ');
1029 pfill(bw->cursor,col,'\t');
1031 bw->cursor->xcol = col; /* Put cursor there even if we can't really go there */
1032 } else if (k == '\t' && bw->o.smartbacks && bw->o.autoindent && pisindent(bw->cursor)>=piscol(bw->cursor)) {
1033 P *p = pdup(bw->cursor);
1034 int n = find_indent(p);
1035 if (n != -1 && pisindent(bw->cursor)==piscol(bw->cursor) && n > pisindent(bw->cursor)) {
1036 if (!pisbol(bw->cursor))
1038 while (joe_isspace(map,(k = pgetc(p))) && k != '\n') {
1039 binsc(bw->cursor, k);
1044 for (x=0;x<bw->o.istep;++x) {
1045 binsc(bw->cursor,bw->o.indentc);
1049 bw->cursor->xcol = piscol(bw->cursor);
1051 } else if (k == '\t' && bw->o.spaces) {
1055 n = bw->cursor->xcol;
1057 n = piscol(bw->cursor);
1059 utype_utf8_sm.state = 0;
1060 utype_utf8_sm.ptr = 0;
1062 n = bw->o.tab - n % bw->o.tab;
1064 utypebw_raw(bw, ' ', 0);
1071 if (bw->o.picture && bw->cursor->xcol!=piscol(bw->cursor))
1072 pfill(bw->cursor,bw->cursor->xcol,' '); /* Why no tabs? */
1075 if(locale_map->type && !no_decode) {
1076 int utf8_char = utf8_decode(&utype_utf8_sm,k);
1084 upd = bw->parent->t->t->updtab[bw->y + bw->cursor->line - bw->top->line];
1087 if (pisblank(bw->cursor))
1088 while (piscol(bw->cursor) < bw->o.lmargin) {
1089 binsc(bw->cursor, ' ');
1093 if (no_decode == 2) {
1094 unsigned char ch = k;
1096 binsm(bw->cursor, &ch, 1);
1097 if (!bw->b->o.charmap->type)
1101 if(locale_map->type && !bw->b->o.charmap->type) {
1102 unsigned char buf[10];
1104 k = from_utf8(bw->b->o.charmap,buf);
1105 } else if(!locale_map->type && bw->b->o.charmap->type) {
1106 unsigned char buf[10];
1107 to_utf8(locale_map,buf,k);
1108 k = utf8_decode_string(buf);
1112 binsc(bw->cursor, k);
1115 /* We need x position before we move cursor */
1116 x = piscol(bw->cursor) - bw->offset;
1119 /* Tabs are weird here... */
1120 if (bw->o.overtype && !piseol(bw->cursor) && k != '\t')
1123 /* Not sure if we're in right position for wordwrap when we're in overtype mode */
1124 if (bw->o.wordwrap && piscol(bw->cursor) > bw->o.rmargin && !joe_isblank(map,k)) {
1125 wrapword(bw->cursor, (long) bw->o.lmargin, bw->o.french, NULL);
1129 bw->cursor->xcol = piscol(bw->cursor);
1131 if (x < 0 || x >= bw->w)
1133 if (bw->cursor->line < bw->top->line || bw->cursor->line >= bw->top->line + bw->h)
1135 if (simple && bw->parent->t->t->sary[bw->y + bw->cursor->line - bw->top->line])
1147 if (simple && !curmacro) {
1149 SCRN *t = bw->parent->t->t;
1150 int y = bw->y + bw->cursor->line - bw->top->line;
1151 int *screen = t->scrn + y * t->co;
1152 int *attr = t->attr + y * t->co;
1155 if (!upd && piseol(bw->cursor) && !bw->o.highlight)
1159 markb->b == bw->b &&
1160 markk->b == bw->b &&
1161 ((!square && bw->cursor->byte >= markb->byte && bw->cursor->byte < markk->byte) ||
1162 ( square && bw->cursor->line >= markb->line && bw->cursor->line <= markk->line && piscol(bw->cursor) >= markb->xcol && piscol(bw->cursor) < markk->xcol)))
1164 outatr(bw->b->o.charmap, t, screen + x, attr + x, x, y, no_decode == 2 ? 0xFFFD : k, atr);
1171 int utypebw(BW *bw, int k)
1173 return utypebw_raw(bw, k, 0);
1178 static B *unicodehist = NULL; /* History of previously entered unicode characters */
1180 static int dounicode(BW *bw, unsigned char *s, void *object, int *notify)
1184 sscanf((char *)s,"%x",&num);
1188 if (bw->b->o.charmap->type)
1189 utypebw_raw(bw, num, 1);
1191 unsigned char buf[8];
1194 utf8_encode(buf,num);
1196 utypebw_raw(bw, buf[x], 1);
1198 bw->cursor->xcol = piscol(bw->cursor);
1205 static int doquote(BW *bw, int c, void *object, int *notify)
1207 unsigned char buf[40];
1209 if (c < 0 || c >= 256) {
1213 switch (quotestate) {
1215 if (c >= '0' && c <= '9') {
1218 joe_snprintf_1((char *)buf, sizeof(buf), "ASCII %c--", c);
1219 if (!mkqwna(bw->parent, sz(buf), doquote, NULL, NULL, notify))
1223 } else if (c == 'u' || c == 'U') {
1224 if (bw->b->o.charmap->type)
1227 if (!wmkpw(bw->parent, US "Unicode (ISO-10646) character in hex (^C to abort): ", &unicodehist, dounicode,
1228 NULL, NULL, NULL, NULL, NULL, locale_map))
1232 } else if (c == 'r' || c == 'R') {
1233 if (!bw->b->o.charmap->type)
1237 if (!mkqwna(bw->parent, sc("ASCII 0x--"), doquote, NULL, NULL, notify))
1241 } else if (c == 'x' || c == 'X') {
1242 if (bw->b->o.charmap->type)
1246 } else if (c == 'o' || c == 'O') {
1248 if (!mkqwna(bw->parent, sc("ASCII 0---"), doquote, NULL, NULL, notify))
1254 if ((c >= 0x40 && c <= 0x5F) || (c >= 'a' && c <= 'z'))
1258 utypebw_raw(bw, c, 1);
1259 bw->cursor->xcol = piscol(bw->cursor);
1263 if (c >= '0' && c <= '9') {
1264 joe_snprintf_2((char *)buf, sizeof(buf), "ASCII %c%c-", quoteval + '0', c);
1265 quoteval = quoteval * 10 + c - '0';
1267 if (!mkqwna(bw->parent, sz(buf), doquote, NULL, NULL, notify))
1274 if (c >= '0' && c <= '9') {
1275 quoteval = quoteval * 10 + c - '0';
1276 utypebw_raw(bw, quoteval, 1);
1277 bw->cursor->xcol = piscol(bw->cursor);
1281 if (c >= '0' && c <= '9') {
1282 joe_snprintf_1((char *)buf, sizeof(buf), "ASCII 0x%c-", c);
1285 if (!mkqwna(bw->parent, sz(buf), doquote, NULL, NULL, notify))
1289 } else if (c >= 'a' && c <= 'f') {
1290 joe_snprintf_1((char *)buf, sizeof(buf), "ASCII 0x%c-", c + 'A' - 'a');
1291 quoteval = c - 'a' + 10;
1293 if (!mkqwna(bw->parent, sz(buf), doquote, NULL, NULL, notify))
1297 } else if (c >= 'A' && c <= 'F') {
1298 joe_snprintf_1((char *)buf, sizeof(buf), "ASCII 0x%c-", c);
1299 quoteval = c - 'A' + 10;
1301 if (!mkqwna(bw->parent, sz(buf), doquote, NULL, NULL, notify))
1308 if (c >= '0' && c <= '9') {
1309 quoteval = quoteval * 16 + c - '0';
1311 utypebw_raw(bw, quoteval, 2);
1312 bw->cursor->xcol = piscol(bw->cursor);
1313 } else if (c >= 'a' && c <= 'f') {
1314 quoteval = quoteval * 16 + c - 'a' + 10;
1316 } else if (c >= 'A' && c <= 'F') {
1317 quoteval = quoteval * 16 + c - 'A' + 10;
1322 if (c >= '0' && c <= '7') {
1323 joe_snprintf_1((char *)buf, sizeof(buf), "ASCII 0%c--", c);
1326 if (!mkqwna(bw->parent, sz(buf), doquote, NULL, NULL, notify))
1333 if (c >= '0' && c <= '7') {
1334 joe_snprintf_2((char *)buf, sizeof(buf), "ASCII 0%c%c-", quoteval + '0', c);
1335 quoteval = quoteval * 8 + c - '0';
1337 if (!mkqwna(bw->parent, sz(buf), doquote, NULL, NULL, notify))
1344 if (c >= '0' && c <= '7') {
1345 quoteval = quoteval * 8 + c - '0';
1346 utypebw_raw(bw, quoteval, 1);
1347 bw->cursor->xcol = piscol(bw->cursor);
1360 if (bw->b->o.charmap->type)
1361 qs = "Ctrl- (or 0-9 for dec. r for hex, o for octal ASCII, x for hex UTF-8)";
1363 qs = "Ctrl- (or 0-9 for dec. x for hex, o for octal ASCII, u for hex UTF-8)";
1365 if (mkqwna(bw->parent, US qs, strlen(qs), doquote, NULL, NULL, NULL))
1371 static int doquote9(BW *bw, int c, void *object, int *notify)
1375 if ((c >= 0x40 && c <= 0x5F) || (c >= 'a' && c <= 'z'))
1380 utypebw_raw(bw, c, 1);
1381 bw->cursor->xcol = piscol(bw->cursor);
1385 static int doquote8(BW *bw, int c, void *object, int *notify)
1388 if (mkqwna(bw->parent, sc("Meta-Ctrl-"), doquote9, NULL, NULL, notify))
1396 utypebw_raw(bw, c, 1);
1397 bw->cursor->xcol = piscol(bw->cursor);
1403 if (mkqwna(bw->parent, sc("Meta-"), doquote8, NULL, NULL, NULL))
1409 extern const unsigned char srchstr[];
1411 static int doctrl(BW *bw, int c, void *object, int *notify)
1413 int org = bw->o.overtype;
1418 if (bw->parent->huh == srchstr && c == '\n') {
1422 utypebw_raw(bw, c, 1);
1423 bw->o.overtype = org;
1424 bw->cursor->xcol = piscol(bw->cursor);
1430 if (mkqwna(bw->parent, sc("Quote"), doctrl, NULL, NULL, NULL))
1436 /* User hit Return. Deal with autoindent.
1441 if (bw->o.overtype) {
1442 p_goto_eol(bw->cursor);
1443 if (piseof(bw->cursor))
1444 binsc(bw->cursor, '\n');
1446 bw->cursor->xcol = piscol(bw->cursor);
1448 P *p = pdup(bw->cursor);
1451 binsc(bw->cursor, '\n'), pgetc(bw->cursor);
1452 /* Suppress autoindent if we're on a space or tab... */
1453 if (bw->o.autoindent && (brch(bw->cursor)!=' ' && brch(bw->cursor)!='\t')) {
1455 while (joe_isspace(bw->b->o.charmap,(c = pgetc(p))) && c != '\n') {
1456 binsc(bw->cursor, c);
1461 bw->cursor->xcol = piscol(bw->cursor);
1470 binsc(bw->cursor,'\n');
1476 static int dosetmark(BW *bw, int c, void *object, int *notify)
1480 if (c >= '0' && c <= ':') {
1481 pdupown(bw->cursor, bw->b->marks + c - '0');
1482 poffline(bw->b->marks[c - '0']);
1484 joe_snprintf_1((char *)msgbuf, JOE_MSGBUFSIZE, "Mark %d set", c - '0');
1485 msgnw(bw->parent, msgbuf);
1494 int usetmark(BW *bw, int c)
1496 if (c >= '0' && c <= ':')
1497 return dosetmark(bw, c, NULL, NULL);
1498 else if (mkqwna(bw->parent, sc("Set mark (0-9):"), dosetmark, NULL, NULL, NULL))
1504 /* Goto book-mark */
1506 static int dogomark(BW *bw, int c, void *object, int *notify)
1510 if (c >= '0' && c <= ':')
1511 if (bw->b->marks[c - '0']) {
1512 pset(bw->cursor, bw->b->marks[c - '0']);
1513 bw->cursor->xcol = piscol(bw->cursor);
1516 joe_snprintf_1((char *)msgbuf, JOE_MSGBUFSIZE, "Mark %d not set", c - '0');
1517 msgnw(bw->parent, msgbuf);
1525 int ugomark(BW *bw, int c)
1527 if (c >= '0' && c <= '9')
1528 return dogomark(bw, c, NULL, NULL);
1529 else if (mkqwna(bw->parent, sc("Goto bookmark (0-9):"), dogomark, NULL, NULL, NULL))
1535 /* Goto next instance of character */
1539 static int dofwrdc(BW *bw, int k, void *object, int *notify)
1546 if (k < 0 || k >= 256) {
1550 q = pdup(bw->cursor);
1552 while ((c = prgetc(q)) != NO_MORE_DATA)
1556 while ((c = pgetc(q)) != NO_MORE_DATA)
1560 if (c == NO_MORE_DATA) {
1561 msgnw(bw->parent, US "Not found");
1565 pset(bw->cursor, q);
1566 bw->cursor->xcol = piscol(bw->cursor);
1572 int ufwrdc(BW *bw, int k)
1575 if (k >= 0 && k < 256)
1576 return dofwrdc(bw, k, NULL, NULL);
1577 else if (mkqw(bw->parent, sc("Fwrd to char: "), dofwrdc, NULL, NULL, NULL))
1583 int ubkwdc(BW *bw, int k)
1586 if (k >= 0 && k < 256)
1587 return dofwrdc(bw, k, NULL, NULL);
1588 else if (mkqw(bw->parent, sc("Bkwd to char: "), dofwrdc, NULL, NULL, NULL))
1594 /* Display a message */
1596 static int domsg(BASE *b, unsigned char *s, void *object, int *notify)
1600 strlcpy((char *)msgbuf, (char *)s, JOE_MSGBUFSIZE);
1602 msgnw(b->parent, *msgbuf ? msgbuf : NULL);
1608 if (wmkpw(b->parent, US "Msg (^C to abort): ", NULL, domsg, NULL, NULL, NULL, NULL, NULL, locale_map))
1616 static int dotxt(BW *bw, unsigned char *s, void *object, int *notify)
1622 for (x = 0; x != sLEN(s); ++x)
1630 if (wmkpw(bw->parent, US "Insert (^C to abort): ", NULL, dotxt, NULL, NULL, utypebw, NULL, NULL, bw->b->o.charmap))