/* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/ed.chared.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */ /* * ed.chared.c: Character editing functions. */ /*- * Copyright (c) 1980, 1991 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #if !defined(lint) && !defined(pdp11) static char *rcsid() { return "$Id: ed.chared.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; } #endif #include "sh.h" #include "ed.h" #include "tw.h" #include "ed.defns.h" /* all routines that start with c_ are private to this set of routines */ static void c_alternativ_key_map __P((int)); static void c_insert __P((int)); static void c_delafter __P((int)); static void c_delbefore __P((int)); static Char *c_prev_word __P((Char *, Char *, int)); static Char *c_next_word __P((Char *, Char *, int)); static Char *c_beg_next_word __P((Char *, Char *, int)); static void c_copy __P((Char *, Char *, int)); static Char *c_number __P((Char *, int *, int)); static Char *c_expand __P((Char *)); static void c_excl __P((Char *)); static void c_substitute __P((void)); static int c_hmatch __P((Char *)); static void c_hsetpat __P((void)); #ifdef COMMENT static void c_get_word __P((Char **, Char **)); #endif static void c_alternativ_key_map(state) int state; { AltKeyMap = state; if (state) Cur_KeyMap = CcAltMap; else Cur_KeyMap = CcKeyMap; } static void c_insert(num) register int num; { register Char *cp; if (LastChar + num >= InputLim) return; /* can't go past end of buffer */ if (Cursor < LastChar) { /* if I must move chars */ for (cp = LastChar; cp >= Cursor; cp--) cp[num] = *cp; } LastChar += num; } static void c_delafter(num) /* delete after dot, with bounds checking */ register int num; { register Char *cp; if (Cursor + num > LastChar) num = LastChar - Cursor;/* bounds check */ if (num > 0) { /* if I can delete anything */ for (cp = Cursor; cp <= LastChar; cp++) *cp = cp[num]; LastChar -= num; } else replacemode = 0; } static void c_delbefore(num) /* delete before dot, with bounds checking */ register int num; { register Char *cp; if (Cursor - num < InputBuf) num = Cursor - InputBuf;/* bounds check */ if (num > 0) { /* if I can delete anything */ for (cp = Cursor - num; cp <= LastChar; cp++) *cp = cp[num]; LastChar -= num; } } static Char * c_prev_word(p, low, n) register Char *p, *low; register int n; { /* to the beginning of the PREVIOUS word, not this one */ p--; while (n--) { while ((p >= low) && (!(isword(*p)))) p--; while ((p >= low) && (isword(*p))) p--; } /* cp now points to one character before the word */ p++; if (p < low) p = low; /* cp now points where we want it */ return (p); } static Char * c_next_word(p, high, n) register Char *p, *high; register int n; { while (n--) { while ((p < high) && (!(isword(*p)))) p++; while ((p < high) && (isword(*p))) p++; } if (p > high) p = high; /* p now points where we want it */ return (p); } static Char * c_beg_next_word(p, high, n) register Char *p, *high; register int n; { while (n--) { while ((p < high) && (isword(*p))) p++; while ((p < high) && (!(isword(*p)))) p++; } if (p > high) p = high; /* p now points where we want it */ return (p); } /* * Expand-History (originally "Magic-Space") code added by * Ray Moody * this is a neat, but odd, addition. */ /* * c_copy is sorta like bcopy() except that we handle overlap between * source and destination memory */ static void c_copy(src, dst, length) register Char *src, *dst; register int length; { if (src > dst) { while (length--) { *dst++ = *src++; } } else { src += length; dst += length; while (length--) { *--dst = *--src; } } } /* * c_number: Ignore character p points to, return number appearing after that. * A '$' by itself means a big number; "$-" is for negative; '^' means 1. * Return p pointing to last char used. */ /* * dval is the number to subtract from for things like $-3 */ static Char * c_number(p, num, dval) register Char *p; register int *num; register int dval; { register int i; register int sign = 1; if (*++p == '^') { *num = 1; return (p); } if (*p == '$') { if (*++p != '-') { *num = NCARGS; /* Handle $ */ return (--p); } sign = -1; /* Handle $- */ ++p; } for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0'); *num = (sign < 0 ? dval - i : i); return (--p); } /* * excl_expand: There is an excl to be expanded to p -- do the right thing * with it and return a version of p advanced over the expanded stuff. Also, * update tsh_cur and related things as appropriate... */ static Char * c_expand(p) register Char *p; { register Char *q; register struct Hist *h = Histlist.Hnext; register struct wordent *l; int i, from, to, dval; bool all_dig; bool been_once = 0; Char *op = p; Char buf[INBUFSIZ]; Char *bend = buf; Char *modbuf, *omodbuf; if (!h) goto excl_err; excl_sw: switch (*(q = p + 1)) { case '^': bend = expand_lex(buf, INBUFSIZ, &h->Hlex, 1, 1); break; case '$': if ((l = (h->Hlex).prev)) bend = expand_lex(buf, INBUFSIZ, l->prev->prev, 0, 0); break; case '*': bend = expand_lex(buf, INBUFSIZ, &h->Hlex, 1, NCARGS); break; default: if (been_once) { /* unknown argument */ /* assume it's a modifier, e.g. !foo:h, and get whole cmd */ bend = expand_lex(buf, INBUFSIZ, &h->Hlex, 0, NCARGS); q -= 2; break; } been_once = 1; if (*q == ':') /* short form: !:arg */ --q; if (*q != HIST) { /* * Search for a space, tab, or colon. See if we have a number (as * in !1234:xyz). Remember the number. */ for (i = 0, all_dig = 1; *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) { /* * PWP: !-4 is a valid history argument too, therefore the test * is if not a digit, or not a - as the first character. */ if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1)) all_dig = 0; else if (*q == '-') all_dig = 2;/* we are sneeky about this */ else i = 10 * i + *q - '0'; } --q; /* * If we have a number, search for event i. Otherwise, search for * a named event (as in !foo). (In this case, I is the length of * the named event). */ if (all_dig) { if (all_dig == 2) i = -i; /* make it negitive */ if (i < 0) /* if !-4 (for example) */ i = eventno + 1 + i; /* remember: i is < 0 */ for (; h; h = h->Hnext) { if (h->Hnum == i) break; } } else { for (i = q - p; h; h = h->Hnext) { if ((l = &h->Hlex)) { if (!Strncmp(p + 1, l->next->word, i)) break; } } } } if (!h) goto excl_err; if (q[1] == ':' || q[1] == '-' || q[1] == '*' || q[1] == '$' || q[1] == '^') { /* get some args */ p = q[1] == ':' ? ++q : q; /* * Go handle !foo:* */ if ((q[1] < '0' || q[1] > '9') && q[1] != '-' && q[1] != '$' && q[1] != '^') goto excl_sw; /* * Go handle !foo:$ */ if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9')) goto excl_sw; /* * Count up the number of words in this event. Store it in dval. * Dval will be fed to number. */ dval = 0; if ((l = h->Hlex.prev)) { for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++); } if (!dval) goto excl_err; if (q[1] == '-') from = 0; else q = c_number(q, &from, dval); if (q[1] == '-') { ++q; if ((q[1] < '0' || q[1] > '9') && q[1] != '$') to = dval - 1; else q = c_number(q, &to, dval); } else if (q[1] == '*') { ++q; to = NCARGS; } else { to = from; } if (from < 0 || to < from) goto excl_err; bend = expand_lex(buf, INBUFSIZ, &h->Hlex, from, to); } else { /* get whole cmd */ bend = expand_lex(buf, INBUFSIZ, &h->Hlex, 0, NCARGS); } break; } /* * Apply modifiers, if any. */ if (q[1] == ':') { *bend = '\0'; omodbuf = buf; while (q[1] == ':' && (modbuf = domod(omodbuf, (int) q[2])) != NOSTR) { if (omodbuf != buf) xfree((ptr_t) omodbuf); omodbuf = modbuf; q += 2; } if (omodbuf != buf) { (void) Strcpy(buf, omodbuf); xfree((ptr_t) omodbuf); bend = Strend(buf); } } /* * Now replace the text from op to q inclusive with the text from buf to * bend. */ q++; /* * Now replace text non-inclusively like a real CS major! */ if (LastChar + (bend - buf) - (q - op) >= InputLim) goto excl_err; c_copy(q, q + (bend - buf) - (q - op), LastChar - q); LastChar += (bend - buf) - (q - op); Cursor += (bend - buf) - (q - op); c_copy(buf, op, (bend - buf)); return (op + (bend - buf)); excl_err: Beep(); return (op + 1); } /* * c_excl: An excl has been found at point p -- back up and find some white * space (or the beginning of the buffer) and properly expand all the excl's * from there up to the current cursor position. We also avoid (trying to) * expanding '>!' */ static void c_excl(p) register Char *p; { register int i; register Char *q; /* * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise, * back p up to just before the current word. */ if ((p[1] == ' ' || p[1] == '\t') && (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) { for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q); if (*q == '>') ++p; } else { while (*p != ' ' && *p != '\t' && p > InputBuf) --p; } /* * Forever: Look for history char. (Stop looking when we find the cursor.) * Count backslashes. Of odd, skip history char. Return if all done. * Expand if even number of backslashes. */ for (;;) { while (*p != HIST && p < Cursor) ++p; for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++); if (i % 2 == 0) ++p; if (p >= Cursor) return; if (i % 2 == 1) p = c_expand(p); } } static void c_substitute() { register Char *p; /* * Start p out one character before the cursor. Move it backwards looking * for white space, the beginning of the line, or a history character. */ for (p = Cursor - 1; p > InputBuf && *p != ' ' && *p != '\t' && *p != HIST; --p); /* * If we found a history character, go expand it. */ if (*p == HIST) c_excl(p); Refresh(); } /* * demi-PUBLIC routines. Any routine that is of type CCRETVAL is an * entry point, called from the CcKeyMap indirected into the * CcFuncTbl array. */ /*VARARGS*/ CCRETVAL v_cmd_mode() { replacemode = 0; c_alternativ_key_map(1); if (Cursor > InputBuf) Cursor--; RefCursor(); return (CC_NORM); } /*VARARGS*/ CCRETVAL e_unassigned() { /* bound to keys that arn't really assigned */ Beep(); flush(); return (CC_NORM); } /*VARARGS*/ CCRETVAL e_insert(c) register Char c; { #ifndef SHORT_STRINGS c &= ASCII; /* no meta chars ever */ #endif if (!c) return (CC_ERROR); /* no NULs in the input ever!! */ if (LastChar + Argument >= InputLim) return (CC_ERROR); /* end of buffer space */ if (Argument == 1) { /* optimize */ if (replacemode == 1) c_delafter(1); else if (replacemode == 2) c_delafter(1); c_insert(1); *Cursor++ = c; DoingArg = 0; /* just in case */ RefPlusOne(); /* fast refresh for one char. */ if (replacemode == 2) (void) v_cmd_mode(); } else { if (replacemode == 1) c_delafter(Argument); else if (replacemode == 2) c_delafter(Argument); c_insert(Argument); while (Argument--) *Cursor++ = c; Refresh(); if (replacemode == 2) (void) v_cmd_mode(); } return (CC_NORM); } int InsertStr(s) /* insert ASCIZ s at cursor (for complete) */ Char *s; { register int len; if ((len = Strlen(s)) <= 0) return -1; if (LastChar + len >= InputLim) return -1; /* end of buffer space */ c_insert(len); while (len--) *Cursor++ = *s++; return 0; } void DeleteBack(n) /* delete the n characters before . */ int n; { if (n <= 0) return; if (Cursor >= &InputBuf[n]) { c_delbefore(n); /* delete before dot */ Cursor -= n; if (Cursor < InputBuf) Cursor = InputBuf; /* bounds check */ } } /*VARARGS*/ CCRETVAL e_digit(c) /* gray magic here */ register Char c; { if (!Isdigit(c)) return (CC_ERROR); /* no NULs in the input ever!! */ if (DoingArg) { /* if doing an arg, add this in... */ if (LastCmd == F_ARGFOUR) /* if last command was ^U */ Argument = c - '0'; else { if (Argument > 1000000) return CC_ERROR; Argument = (Argument * 10) + (c - '0'); } return (CC_ARGHACK); } else { if (LastChar + 1 >= InputLim) return CC_ERROR; /* end of buffer space */ c_insert(1); *Cursor++ = c; DoingArg = 0; /* just in case */ RefPlusOne(); /* fast refresh for one char. */ } return (CC_NORM); } /*VARARGS*/ CCRETVAL e_argdigit(c) /* for ESC-n */ register Char c; { c &= ASCII; if (!Isdigit(c)) return (CC_ERROR); /* no NULs in the input ever!! */ if (DoingArg) { /* if doing an arg, add this in... */ if (Argument > 1000000) return CC_ERROR; Argument = (Argument * 10) + (c - '0'); } else { /* else starting an argument */ Argument = c - '0'; DoingArg = 1; } return (CC_ARGHACK); } /*VARARGS*/ CCRETVAL v_zero(c) /* command mode 0 for vi */ register Char c; { if (DoingArg) { /* if doing an arg, add this in... */ if (Argument > 1000000) return CC_ERROR; Argument = (Argument * 10) + (c - '0'); return (CC_ARGHACK); } else { /* else starting an argument */ Cursor = InputBuf; RefCursor(); /* move the cursor */ return (CC_NORM); } } /*VARARGS*/ CCRETVAL e_newline() { /* always ignore argument */ PastBottom(); *LastChar++ = '\n'; /* for the benifit of CSH */ *LastChar = '\0'; /* just in case */ return (CC_NEWLINE); /* we must do a ResetInLine later */ } /*VARARGS*/ CCRETVAL e_send_eof() { /* for when ^D is ONLY send-eof */ PastBottom(); *LastChar = '\0'; /* just in case */ #ifdef notdef ResetInLine(); /* reset the input pointers */ #endif return (CC_EOF); } /*VARARGS*/ CCRETVAL e_complete() { *LastChar = '\0'; /* just in case */ return (CC_COMPLETE); } /*VARARGS*/ CCRETVAL v_cm_complete() { if (Cursor < LastChar) Cursor++; *LastChar = '\0'; /* just in case */ return (CC_COMPLETE); } /*VARARGS*/ CCRETVAL e_toggle_hist() { struct Hist *hp; int h; *LastChar = '\0'; /* just in case */ if (Hist_num <= 0) { return CC_ERROR; } hp = Histlist.Hnext; if (hp == NULL) { /* this is only if no history */ return (CC_ERROR); } for (h = 1; h < Hist_num; h++) hp = hp->Hnext; if (!Cur_HistLit) { if (hp->histline) { copyn(InputBuf, hp->histline, INBUFSIZ); Cur_HistLit = 1; } else { return CC_ERROR; } } else { (void) sprlex(InputBuf, &hp->Hlex); Cur_HistLit = 0; } LastChar = InputBuf + Strlen(InputBuf); if (LastChar > InputBuf) { if (LastChar[-1] == '\n') LastChar--; if (LastChar[-1] == ' ') LastChar--; if (LastChar < InputBuf) LastChar = InputBuf; } Cursor = LastChar; return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_up_hist() { struct Hist *hp; int hnumcntr; Char beep = 0; *LastChar = '\0'; /* just in case */ if (Hist_num == 0) { /* save the current buffer away */ copyn(HistBuf, InputBuf, INBUFSIZ); LastHist = HistBuf + (LastChar - InputBuf); } hp = Histlist.Hnext; if (hp == NULL) { /* this is only if no history */ return (CC_ERROR); } Hist_num += Argument; for (hnumcntr = 1; hnumcntr < Hist_num; hnumcntr++) { if ((hp->Hnext) == NULL) { Hist_num = hnumcntr; beep = 1; break; } hp = hp->Hnext; } if (HistLit && hp->histline) { copyn(InputBuf, hp->histline, INBUFSIZ); Cur_HistLit = 1; } else { (void) sprlex(InputBuf, &hp->Hlex); Cur_HistLit = 0; } LastChar = InputBuf + Strlen(InputBuf); if (LastChar > InputBuf) { if (LastChar[-1] == '\n') LastChar--; if (LastChar[-1] == ' ') LastChar--; if (LastChar < InputBuf) LastChar = InputBuf; } Cursor = LastChar; Refresh(); if (beep) return (CC_ERROR); else return (CC_NORM); /* was CC_UP_HIST */ } /*VARARGS*/ CCRETVAL e_d_hist() { struct Hist *hp; int hnumcntr; *LastChar = '\0'; /* just in case */ Hist_num -= Argument; if (Hist_num < 0) { Hist_num = 0; return (CC_ERROR); /* make it beep */ } if (Hist_num == 0) { /* if really the current line */ copyn(InputBuf, HistBuf, INBUFSIZ); LastChar = InputBuf + (LastHist - HistBuf); Cursor = LastChar; return (CC_REFRESH); } hp = Histlist.Hnext; if (hp == NULL) return (CC_ERROR); for (hnumcntr = 1; hnumcntr < Hist_num; hnumcntr++) { if ((hp->Hnext) == NULL) { Hist_num = hnumcntr; return (CC_ERROR); } hp = hp->Hnext; } if (HistLit && hp->histline) { copyn(InputBuf, hp->histline, INBUFSIZ); Cur_HistLit = 1; } else { (void) sprlex(InputBuf, &hp->Hlex); Cur_HistLit = 0; } LastChar = InputBuf + Strlen(InputBuf); if (LastChar > InputBuf) { if (LastChar[-1] == '\n') LastChar--; if (LastChar[-1] == ' ') LastChar--; if (LastChar < InputBuf) LastChar = InputBuf; } Cursor = LastChar; return (CC_REFRESH); } static Char patbuf[INBUFSIZ]; static int patlen = 0; /* * c_hmatch() return True if the pattern matches the prefix */ static int c_hmatch(str) Char *str; { if (Strncmp(patbuf, str, patlen) == 0) return 1; return Gmatch(str, patbuf); } /* * c_hsetpat(): Set the history seatch pattern */ static void c_hsetpat() { if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) { patlen = Cursor - InputBuf; if (patlen >= INBUFSIZ) patlen = INBUFSIZ -1; (void) Strncpy(patbuf, InputBuf, patlen); patbuf[patlen] = '\0'; } #ifdef SDEBUG xprintf("\nHist_num = %d\n", Hist_num); xprintf("patlen = %d\n", patlen); xprintf("patbuf = \"%s\"\n", short2str(patbuf)); #endif } /*VARARGS*/ CCRETVAL e_up_search_hist() { struct Hist *hp; int h; bool found = 0; *LastChar = '\0'; /* just in case */ if (Hist_num < 0) { xprintf("tcsh: e_up_search_hist(): Hist_num < 0; resetting.\n"); Hist_num = 0; return (CC_ERROR); } if (Hist_num == 0) { copyn(HistBuf, InputBuf, INBUFSIZ); LastHist = HistBuf + (LastChar - InputBuf); } hp = Histlist.Hnext; if (hp == NULL) return (CC_ERROR); c_hsetpat(); for (h = 1; h <= Hist_num; h++) hp = hp->Hnext; while (hp != NULL) { if (hp->histline == NULL) { Char sbuf[BUFSIZ]; hp->histline = Strsave(sprlex(sbuf, &hp->Hlex)); } #ifdef SDEBUG xprintf("Comparing with \"%s\"\n", short2str(hp->histline)); #endif if (c_hmatch(hp->histline)) { found++; break; } h++; hp = hp->Hnext; } if (!found) return (CC_ERROR); Hist_num = h; if (HistLit && hp->histline) { copyn(InputBuf, hp->histline, INBUFSIZ); Cur_HistLit = 1; } else { (void) sprlex(InputBuf, &hp->Hlex); Cur_HistLit = 0; } LastChar = InputBuf + Strlen(InputBuf); if (LastChar > InputBuf) { if (LastChar[-1] == '\n') LastChar--; if (LastChar[-1] == ' ') LastChar--; if (LastChar < InputBuf) LastChar = InputBuf; } Cursor = LastChar; return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_d_search_hist() { struct Hist *hp, *hpt = NULL; int h; bool found = 0; *LastChar = '\0'; /* just in case */ if (Hist_num == 0) return (CC_ERROR); hp = Histlist.Hnext; if (hp == 0) return (CC_ERROR); c_hsetpat(); for (h = 1; h < Hist_num && hp; h++) { if (hp->histline == NULL) { Char sbuf[BUFSIZ]; hp->histline = Strsave(sprlex(sbuf, &hp->Hlex)); } #ifdef SDEBUG xprintf("Comparing with \"%s\"\n", short2str(hp->histline)); #endif if (c_hmatch(hp->histline)) { found = h; hpt = hp; } hp = hp->Hnext; } if (!found) { /* is it the current history number? */ if (c_hmatch(HistBuf)) { copyn(InputBuf, HistBuf, INBUFSIZ); LastChar = InputBuf + (LastHist - HistBuf); Hist_num = 0; Cursor = LastChar; return (CC_REFRESH); } else { return (CC_ERROR); } } Hist_num = found; hp = hpt; if (HistLit && hp->histline) { copyn(InputBuf, hp->histline, INBUFSIZ); Cur_HistLit = 1; } else { (void) sprlex(InputBuf, &hp->Hlex); Cur_HistLit = 0; } LastChar = InputBuf + Strlen(InputBuf); if (LastChar > InputBuf) { if (LastChar[-1] == '\n') LastChar--; if (LastChar[-1] == ' ') LastChar--; if (LastChar < InputBuf) LastChar = InputBuf; } Cursor = LastChar; return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_helpme() { PastBottom(); *LastChar = '\0'; /* just in case */ return (CC_HELPME); } /*VARARGS*/ CCRETVAL e_corr() { *LastChar = '\0'; /* just in case */ return (CC_CORRECT); } /*VARARGS*/ CCRETVAL e_corrl() { *LastChar = '\0'; /* just in case */ return (CC_CORRECT_L); } /*VARARGS*/ CCRETVAL e_run_fg_editor() { register struct process *pp; extern bool tellwhat; if ((pp = find_stop_ed()) != PNULL) { /* save our editor state so we can restore it */ tellwhat = 1; copyn(WhichBuf, InputBuf, INBUFSIZ); LastWhich = WhichBuf + (LastChar - InputBuf); CursWhich = WhichBuf + (Cursor - InputBuf); HistWhich = Hist_num; Hist_num = 0; /* for the history commands */ /* put the tty in a sane mode */ PastBottom(); (void) Cookedmode(); /* make sure the tty is set up correctly */ /* do it! */ fg_proc_entry(pp); (void) Rawmode(); /* go on */ Refresh(); tellwhat = 0; } return (CC_NORM); } /*VARARGS*/ CCRETVAL e_l_choices() { PastBottom(); *LastChar = '\0'; /* just in case */ return (CC_LIST_CHOICES); } /*VARARGS*/ CCRETVAL e_l_glob() { PastBottom(); *LastChar = '\0'; /* just in case */ return (CC_LIST_GLOB); } /*VARARGS*/ CCRETVAL e_ex_glob() { *LastChar = '\0'; /* just in case */ return (CC_EXPAND_GLOB); } /*VARARGS*/ CCRETVAL e_ex_vars() { *LastChar = '\0'; /* just in case */ return (CC_EXPAND_VARS); } /*VARARGS*/ CCRETVAL e_which() { /* do a fast command line which(1) */ PastBottom(); *LastChar = '\0'; /* just in case */ return (CC_WHICH); } /*VARARGS*/ CCRETVAL e_last_item() { /* insert the last element of the prev. cmd */ register Char *cp; register struct Hist *hp; register struct wordent *wp, *firstp; register int i; if (Argument <= 0) return (CC_ERROR); hp = Histlist.Hnext; if (hp == NULL) { /* this is only if no history */ return (CC_ERROR); } wp = (hp->Hlex).prev; if (wp->prev == (struct wordent *) NULL) return (CC_ERROR); /* an empty history entry */ firstp = (hp->Hlex).next; for (i = 0; i < Argument; i++) { /* back up arg words in lex */ wp = wp->prev; if (wp == firstp) break; } while (i > 0) { cp = wp->word; if (!cp) return (CC_ERROR); if (InsertStr(cp)) return (CC_ERROR); wp = wp->next; i--; } return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_yank_kill() { /* almost like GnuEmacs */ register Char *kp, *cp; if (LastKill == KillBuf) /* if zero content */ return (CC_ERROR); if (LastChar + (LastKill - KillBuf) >= InputLim) return (CC_ERROR); /* end of buffer space */ /* else */ Mark = Cursor; /* set the mark */ cp = Cursor; /* for speed */ c_insert(LastKill - KillBuf); /* open the space, */ for (kp = KillBuf; kp < LastKill; kp++) /* copy the chars */ *cp++ = *kp; if (Argument == 1) /* if an arg, cursor at beginning */ Cursor = cp; /* else cursor at end */ return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_delprev() { if (Cursor > InputBuf) { c_delbefore(Argument); /* delete before dot */ Cursor -= Argument; if (Cursor < InputBuf) Cursor = InputBuf; /* bounds check */ return (CC_REFRESH); } else { return (CC_ERROR); } } /*VARARGS*/ CCRETVAL e_dwrdprev() { register Char *cp, *p, *kp; if (Cursor == InputBuf) return (CC_ERROR); /* else */ cp = c_prev_word(Cursor, InputBuf, Argument); for (p = cp, kp = KillBuf; p < Cursor; p++) /* save the text */ *kp++ = *p; LastKill = kp; c_delbefore(Cursor - cp); /* delete before dot */ Cursor = cp; if (Cursor < InputBuf) Cursor = InputBuf; /* bounds check */ return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_delnext() { if (Cursor == LastChar) { /* if I'm at the end */ if (Cursor == InputBuf && !VImode) { /* if I'm also at the beginning */ so_write(STReof, 4);/* then do a EOF */ flush(); return (CC_EOF); } else { return (CC_ERROR); } } else { c_delafter(Argument); /* delete after dot */ if (Cursor > LastChar) Cursor = LastChar; /* bounds check */ return (CC_REFRESH); } } /*VARARGS*/ CCRETVAL e_l_delnext() { if (Cursor == LastChar) { /* if I'm at the end */ if (Cursor == InputBuf) { /* if I'm also at the beginning */ so_write(STReof, 4);/* then do a EOF */ flush(); return (CC_EOF); } else { PastBottom(); *LastChar = '\0'; /* just in case */ return (CC_LIST_CHOICES); } } else { c_delafter(Argument); /* delete after dot */ if (Cursor > LastChar) Cursor = LastChar; /* bounds check */ return (CC_REFRESH); } } CCRETVAL e_l_eof() { if (Cursor == LastChar && Cursor == InputBuf) { so_write(STReof, 4); /* then do a EOF */ flush(); return (CC_EOF); } else { PastBottom(); *LastChar = '\0'; /* just in case */ return (CC_LIST_CHOICES); } } /*VARARGS*/ CCRETVAL e_dwrdnext() { register Char *cp, *p, *kp; if (Cursor == LastChar) return (CC_ERROR); /* else */ cp = c_next_word(Cursor, LastChar, Argument); for (p = Cursor, kp = KillBuf; p < cp; p++) /* save the text */ *kp++ = *p; LastKill = kp; c_delafter(cp - Cursor); /* delete after dot */ /* Cursor = Cursor; */ if (Cursor > LastChar) Cursor = LastChar; /* bounds check */ return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_toend() { Cursor = LastChar; RefCursor(); /* move the cursor */ return (CC_NORM); } /*VARARGS*/ CCRETVAL e_tobeg() { Cursor = InputBuf; RefCursor(); /* move the cursor */ return (CC_NORM); } /*VARARGS*/ CCRETVAL e_killend() { register Char *kp, *cp; cp = Cursor; kp = KillBuf; while (cp < LastChar) *kp++ = *cp++; /* copy it */ LastKill = kp; LastChar = Cursor; /* zap! -- delete to end */ return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_killbeg() { register Char *kp, *cp; cp = InputBuf; kp = KillBuf; while (cp < Cursor) *kp++ = *cp++; /* copy it */ LastKill = kp; c_delbefore(Cursor - InputBuf); Cursor = InputBuf; /* zap! */ return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_killall() { register Char *kp, *cp; cp = InputBuf; kp = KillBuf; while (cp < LastChar) *kp++ = *cp++; /* copy it */ LastKill = kp; LastChar = InputBuf; /* zap! -- delete all of it */ Cursor = InputBuf; return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_killregion() { register Char *kp, *cp; if (!Mark) return (CC_ERROR); if (Mark > Cursor) { cp = Cursor; kp = KillBuf; while (cp < Mark) *kp++ = *cp++; /* copy it */ LastKill = kp; c_delafter(cp - Cursor);/* delete it */ } else { /* mark is before cursor */ cp = Mark; kp = KillBuf; while (cp < Cursor) *kp++ = *cp++; /* copy it */ LastKill = kp; c_delbefore(cp - Mark); Cursor = Mark; } return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_copyregion() { register Char *kp, *cp; if (!Mark) return (CC_ERROR); if (Mark > Cursor) { cp = Cursor; kp = KillBuf; while (cp < Mark) *kp++ = *cp++; /* copy it */ LastKill = kp; } else { /* mark is before cursor */ cp = Mark; kp = KillBuf; while (cp < Cursor) *kp++ = *cp++; /* copy it */ LastKill = kp; } return (CC_NORM); /* don't even need to Refresh() */ } /*VARARGS*/ CCRETVAL e_charswitch() { register Char c; if (Cursor < LastChar) { if (LastChar <= &InputBuf[1]) { return (CC_ERROR); } else { Cursor++; } } if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */ c = Cursor[-2]; Cursor[-2] = Cursor[-1]; Cursor[-1] = c; return (CC_REFRESH); } else { return (CC_ERROR); } } /*VARARGS*/ CCRETVAL e_gcharswitch() { /* gosmacs style ^T */ register Char c; if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */ c = Cursor[-2]; Cursor[-2] = Cursor[-1]; Cursor[-1] = c; return (CC_REFRESH); } else { return (CC_ERROR); } } /*VARARGS*/ CCRETVAL e_charback() { if (Cursor > InputBuf) { Cursor -= Argument; if (Cursor < InputBuf) Cursor = InputBuf; RefCursor(); return (CC_NORM); } else { return (CC_ERROR); } } /*VARARGS*/ CCRETVAL e_wordback() { if (Cursor == InputBuf) return (CC_ERROR); /* else */ Cursor = c_prev_word(Cursor, InputBuf, Argument); /* does a bounds check */ RefCursor(); return (CC_NORM); } /*VARARGS*/ CCRETVAL e_charfwd() { if (Cursor < LastChar) { Cursor += Argument; if (Cursor > LastChar) Cursor = LastChar; RefCursor(); return (CC_NORM); } else { return (CC_ERROR); } } /*VARARGS*/ CCRETVAL e_wordfwd() { if (Cursor == LastChar) return (CC_ERROR); /* else */ Cursor = c_next_word(Cursor, LastChar, Argument); RefCursor(); return (CC_NORM); } /*VARARGS*/ CCRETVAL v_wordbegnext() { if (Cursor == LastChar) return (CC_ERROR); /* else */ Cursor = c_beg_next_word(Cursor, LastChar, Argument); RefCursor(); return (CC_NORM); } #ifdef COMMENT /* by: Brian Allison */ static void c_get_word(begin, end) Char **begin; Char **end; { Char *cp; cp = &Cursor[0]; while (Argument--) { while ((cp <= LastChar) && (isword(*cp))) cp++; *end = --cp; while ((cp >= InputBuf) && (isword(*cp))) cp--; *begin = ++cp; } } #endif /* COMMENT */ /*VARARGS*/ CCRETVAL e_uppercase() { Char *cp, *end; end = c_next_word(Cursor, LastChar, Argument); for (cp = Cursor; cp < end; cp++) /* PWP: was cp=begin */ if (Islower(*cp)) *cp = Toupper(*cp); Cursor = end; if (Cursor > LastChar) Cursor = LastChar; return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_capitolcase() { Char *cp, *end; end = c_next_word(Cursor, LastChar, Argument); cp = Cursor; for (; cp < end; cp++) { if (Isalpha(*cp)) { if (Islower(*cp)) *cp = Toupper(*cp); cp++; break; } } for (; cp < end; cp++) if (Isupper(*cp)) *cp = Tolower(*cp); Cursor = end; if (Cursor > LastChar) Cursor = LastChar; return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_lowercase() { Char *cp, *end; end = c_next_word(Cursor, LastChar, Argument); for (cp = Cursor; cp < end; cp++) if (Isupper(*cp)) *cp = Tolower(*cp); Cursor = end; if (Cursor > LastChar) Cursor = LastChar; return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_set_mark() { Mark = Cursor; return (CC_NORM); } /*VARARGS*/ CCRETVAL e_exchange_mark() { register Char *cp; cp = Cursor; Cursor = Mark; Mark = cp; RefCursor(); return (CC_NORM); } /*VARARGS*/ CCRETVAL e_argfour() { /* multiply current argument by 4 */ if (Argument > 1000000) return CC_ERROR; DoingArg = 1; Argument *= 4; return (CC_ARGHACK); } /*VARARGS*/ CCRETVAL e_quote() { Char ch; int num; QModeOn(); num = G_N_Char(&ch); QModeOff(); if (num == 1) return e_insert(ch); else return e_send_eof(); } /*VARARGS*/ CCRETVAL e_metanext() { MetaNext = 1; return (CC_ARGHACK); /* preserve argument */ } #ifdef notdef /*VARARGS*/ CCRETVAL e_extendnext() { Cur_KeyMap = CcAltMap; return (CC_ARGHACK); /* preserve argument */ } #endif /*VARARGS*/ CCRETVAL v_insbeg() { /* move to beginning of line and start vi * insert mode */ Cursor = InputBuf; RefCursor(); /* move the cursor */ c_alternativ_key_map(0); return (CC_NORM); } /*VARARGS*/ CCRETVAL v_replone() { /* vi mode overwrite one character */ c_alternativ_key_map(0); replacemode = 2; return (CC_NORM); } /*VARARGS*/ CCRETVAL v_replmode() { /* vi mode start overwriting */ c_alternativ_key_map(0); replacemode = 1; return (CC_NORM); } /*VARARGS*/ CCRETVAL v_s_char() { /* vi mode substitute for one char */ c_delafter(Argument); c_alternativ_key_map(0); return (CC_REFRESH); } /*VARARGS*/ CCRETVAL v_s_line() { /* vi mode replace whole line */ (void) e_killall(); c_alternativ_key_map(0); return (CC_NORM); } /*VARARGS*/ CCRETVAL v_chgtoend() { /* vi mode change to end of line */ (void) e_killend(); c_alternativ_key_map(0); return (CC_REFRESH); } /*VARARGS*/ CCRETVAL v_insert() { /* vi mode start inserting */ c_alternativ_key_map(0); return (CC_NORM); } /*VARARGS*/ CCRETVAL v_add() { /* vi mode start adding */ c_alternativ_key_map(0); if (Cursor < LastChar) { Cursor++; if (Cursor > LastChar) Cursor = LastChar; RefCursor(); } return (CC_NORM); } /*VARARGS*/ CCRETVAL v_addend() { /* vi mode to add at end of line */ c_alternativ_key_map(0); Cursor = LastChar; RefCursor(); return (CC_NORM); } /*VARARGS*/ CCRETVAL v_change_case() { char c; if (Cursor < LastChar) { c = *Cursor; if (Isupper(c)) *Cursor++ = Tolower(c); else if (Islower(c)) *Cursor++ = Toupper(c); else Cursor++; RefPlusOne(); /* fast refresh for one char */ return (CC_NORM); } return (CC_ERROR); } /*VARARGS*/ CCRETVAL e_expand() { register Char *p; extern bool justpr; for (p = InputBuf; Isspace(*p); p++); if (p == LastChar) return (CC_ERROR); justpr++; Expand++; return (e_newline()); } /*VARARGS*/ CCRETVAL e_startover() { /* erase all of current line, start again */ ResetInLine(); /* reset the input pointers */ return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_redisp() { ClearLines(); ClearDisp(); return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_cleardisp() { ClearScreen(); /* clear the whole real screen */ ClearDisp(); /* reset everything */ return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_t_int() { /* do no editing */ return (CC_NORM); } /*VARARGS*/ CCRETVAL e_insovr() { replacemode = !replacemode; return (CC_NORM); } /*VARARGS*/ CCRETVAL e_t_dsusp() { /* do no editing */ return (CC_NORM); } /*VARARGS*/ CCRETVAL e_t_flusho() { /* do no editing */ return (CC_NORM); } /*VARARGS*/ CCRETVAL e_t_quit() { /* do no editing */ return (CC_NORM); } /*VARARGS*/ CCRETVAL e_t_tsusp() { /* do no editing */ return (CC_NORM); } /*VARARGS*/ CCRETVAL e_t_stopo() { /* do no editing */ return (CC_NORM); } /*VARARGS*/ CCRETVAL e_ex_history() { *LastChar = '\0'; /* just in case */ c_substitute(); return (CC_NORM); } /*VARARGS*/ CCRETVAL e_magic_space() { *LastChar = '\0'; /* just in case */ c_substitute(); return (e_insert(' ')); } /*VARARGS*/ CCRETVAL e_copyprev() { register Char *cp, *oldc, *dp; if (Cursor == InputBuf) return (CC_ERROR); /* else */ oldc = Cursor; /* does a bounds check */ cp = c_prev_word(Cursor, InputBuf, Argument); c_insert(oldc - cp); for (dp = oldc; cp < oldc && dp < LastChar; cp++) *dp++ = *cp; Cursor = dp; /* put cursor at end */ return (CC_REFRESH); } /*VARARGS*/ CCRETVAL e_t_starto() { /* do no editing */ return (CC_NORM); } #ifdef notdef void MoveCursor(n) /* move cursor + right - left char */ int n; { Cursor = Cursor + n; if (Cursor < InputBuf) Cursor = InputBuf; if (Cursor > LastChar) Cursor = LastChar; return; } Char * GetCursor() { return (Cursor); } int PutCursor(p) Char *p; { if (p < InputBuf || p > LastChar) return 1; /* Error */ Cursor = p; return 0; } #endif