/* Note the return value for this is: * meABORT - there was a major failure (i.e. couldn't open the file) * meFALSE - user quit * meTRUE - succeded * this is used by the exit function which ignore the major failures */ static int regTestSave(meRegNode *sroot, int flags) { /* if its not a file or not changed or the changes are to be discarded * then nothing to do */ if(!(sroot->mode & meREGMODE_FROOT) || !(sroot->mode & meREGMODE_CHANGE) || (sroot->mode & meREGMODE_DISCARD)) return meTRUE ; if((flags & 0x01) && !(sroot->mode & meREGMODE_AUTO)) { meUByte prompt[meBUF_SIZE_MAX] ; int ret ; meStrcpy(prompt,(sroot->value != NULL) ? sroot->value:sroot->name) ; meStrcat(prompt,": Save registry") ; if((ret = mlyesno(prompt)) == meABORT) { ctrlg(meFALSE,1) ; return meFALSE ; } if(ret == meFALSE) return meTRUE ; } return regSave(sroot,NULL,sroot->mode) ; }
int frameCreate(int f, int n) { meFrame *frame, *sf ; int menuDepth ; #if MEOPT_MWFRAME if(!f || (n & 2)) sf = NULL ; else if(n & 1) sf = frameCur ; else return ctrlg(0,1) ; #else if((n & 1) == 0) return ctrlg(0,1) ; sf = frameCur ; #endif /* these functions cannot use meMalloc as they are used to init ME, * so if they fail we must warn of the malloc failure */ if(((frame = meFrameInit(sf)) == NULL) || (meFrameInitWindow(frame,frameCur->bufferCur) <= 0)) return mlwrite(MWCURSOR|MWABORT|MWWAIT,(meUByte *)"[Failed to create new frame]") ; #if MEOPT_MWFRAME if(sf != NULL) #endif frame->flags |= meFRAME_HIDDEN ; menuDepth = frameCur->menuDepth ; frame->next = frameCur->next ; restoreWindWSet(frame->windowCur,frameCur->windowCur) ; frameCur->next = frame ; meFrameMakeCur(frame, 0) ; if(menuDepth) frameSetupMenuLine(menuDepth) ; sgarbf = true; /* Garbage the screen */ return true ; }
/* * Ask a "yes" or "no" question. Return ABORT if the user answers the * question with the abort ("^G") character. Return FALSE for "no" and * TRUE for "yes". No formatting services are available. No newline * required. */ int eyorn(const char *sp) { int s; if (inmacro) return (TRUE); ewprintf("%s? (y or n) ", sp); for (;;) { s = getkey(FALSE); if (s == 'y' || s == 'Y' || s == ' ') return (TRUE); if (s == 'n' || s == 'N' || s == CCHR('M')) return (FALSE); if (s == CCHR('G')) return (ctrlg(FFRAND, 1)); ewprintf("Please answer y or n. %s? (y or n) ", sp); } /* NOTREACHED */ }
static char * veread(const char *fp, char *buf, size_t nbuf, int flag, va_list ap) { int dynbuf = (buf == NULL); int cpos, epos; /* cursor, end position in buf */ int c, i, y; int cplflag = FALSE; /* display completion list */ int cwin = FALSE; /* completion list created */ int mr = 0; /* match left arrow */ int ml = 0; /* match right arrow */ int esc = 0; /* position in esc pattern */ struct buffer *bp; /* completion list buffer */ struct mgwin *wp; /* window for compl list */ int match; /* esc match found */ int cc, rr; /* saved ttcol, ttrow */ char *ret; /* return value */ static char emptyval[] = ""; /* XXX hackish way to return err msg*/ if (inmacro) { if (dynbuf) { if ((buf = malloc(maclcur->l_used + 1)) == NULL) return (NULL); } else if (maclcur->l_used >= nbuf) return (NULL); bcopy(maclcur->l_text, buf, maclcur->l_used); buf[maclcur->l_used] = '\0'; maclcur = maclcur->l_fp; return (buf); } epos = cpos = 0; ml = mr = esc = 0; cplflag = FALSE; if ((flag & EFNEW) != 0 || ttrow != nrow - 1) { ttcolor(CTEXT); ttmove(nrow - 1, 0); epresf = TRUE; } else eputc(' '); eformat(fp, ap); if ((flag & EFDEF) != 0) { if (buf == NULL) return (NULL); eputs(buf); epos = cpos += strlen(buf); } tteeol(); ttflush(); for (;;) { c = getkey(FALSE); if ((flag & EFAUTO) != 0 && c == CCHR('I')) { if (cplflag == TRUE) { complt_list(flag, buf, cpos); cwin = TRUE; } else if (complt(flag, c, buf, nbuf, epos, &i) == TRUE) { cplflag = TRUE; epos += i; cpos = epos; } continue; } cplflag = FALSE; if (esc > 0) { /* ESC sequence started */ match = 0; if (ml == esc && key_left[ml] && c == key_left[ml]) { match++; if (key_left[++ml] == '\0') { c = CCHR('B'); esc = 0; } } if (mr == esc && key_right[mr] && c == key_right[mr]) { match++; if (key_right[++mr] == '\0') { c = CCHR('F'); esc = 0; } } if (match == 0) { esc = 0; continue; /* hack. how do we know esc pattern is done? */ } if (esc > 0) { esc++; continue; } } switch (c) { case CCHR('A'): /* start of line */ while (cpos > 0) { if (ISCTRL(buf[--cpos]) != FALSE) { ttputc('\b'); --ttcol; } ttputc('\b'); --ttcol; } ttflush(); break; case CCHR('D'): if (cpos != epos) { tteeol(); epos--; rr = ttrow; cc = ttcol; for (i = cpos; i < epos; i++) { buf[i] = buf[i + 1]; eputc(buf[i]); } ttmove(rr, cc); ttflush(); } break; case CCHR('E'): /* end of line */ while (cpos < epos) { eputc(buf[cpos++]); } ttflush(); break; case CCHR('B'): /* back */ if (cpos > 0) { if (ISCTRL(buf[--cpos]) != FALSE) { ttputc('\b'); --ttcol; } ttputc('\b'); --ttcol; ttflush(); } break; case CCHR('F'): /* forw */ if (cpos < epos) { eputc(buf[cpos++]); ttflush(); } break; case CCHR('Y'): /* yank from kill buffer */ i = 0; while ((y = kremove(i++)) >= 0 && y != '\n') { int t; if (dynbuf && epos + 1 >= nbuf) { void *newp; size_t newsize = epos + epos + 16; if ((newp = realloc(buf, newsize)) == NULL) goto memfail; buf = newp; nbuf = newsize; } if (!dynbuf && epos + 1 >= nbuf) { ewprintf("Line too long"); return (emptyval); } for (t = epos; t > cpos; t--) buf[t] = buf[t - 1]; buf[cpos++] = (char)y; epos++; eputc((char)y); cc = ttcol; rr = ttrow; for (t = cpos; t < epos; t++) eputc(buf[t]); ttmove(rr, cc); } ttflush(); break; case CCHR('K'): /* copy here-EOL to kill buffer */ kdelete(); for (i = cpos; i < epos; i++) kinsert(buf[i], KFORW); tteeol(); epos = cpos; ttflush(); break; case CCHR('['): ml = mr = esc = 1; break; case CCHR('J'): c = CCHR('M'); /* FALLTHROUGH */ case CCHR('M'): /* return, done */ /* if there's nothing in the minibuffer, abort */ if (epos == 0 && !(flag & EFNUL)) { (void)ctrlg(FFRAND, 0); ttflush(); return (NULL); } if ((flag & EFFUNC) != 0) { if (complt(flag, c, buf, nbuf, epos, &i) == FALSE) continue; if (i > 0) epos += i; } buf[epos] = '\0'; if ((flag & EFCR) != 0) { ttputc(CCHR('M')); ttflush(); } if (macrodef) { struct line *lp; if ((lp = lalloc(cpos)) == NULL) goto memfail; lp->l_fp = maclcur->l_fp; maclcur->l_fp = lp; lp->l_bp = maclcur; maclcur = lp; bcopy(buf, lp->l_text, cpos); } ret = buf; goto done; case CCHR('G'): /* bell, abort */ eputc(CCHR('G')); (void)ctrlg(FFRAND, 0); ttflush(); ret = NULL; goto done; case CCHR('H'): /* rubout, erase */ case CCHR('?'): if (cpos != 0) { y = buf[--cpos]; epos--; ttputc('\b'); ttcol--; if (ISCTRL(y) != FALSE) { ttputc('\b'); ttcol--; } rr = ttrow; cc = ttcol; for (i = cpos; i < epos; i++) { buf[i] = buf[i + 1]; eputc(buf[i]); } ttputc(' '); if (ISCTRL(y) != FALSE) { ttputc(' '); ttputc('\b'); } ttputc('\b'); ttmove(rr, cc); ttflush(); } break; case CCHR('X'): /* kill line */ case CCHR('U'): while (cpos != 0) { ttputc('\b'); ttputc(' '); ttputc('\b'); --ttcol; if (ISCTRL(buf[--cpos]) != FALSE) { ttputc('\b'); ttputc(' '); ttputc('\b'); --ttcol; } epos--; } ttflush(); break; case CCHR('W'): /* kill to beginning of word */ while ((cpos > 0) && !ISWORD(buf[cpos - 1])) { ttputc('\b'); ttputc(' '); ttputc('\b'); --ttcol; if (ISCTRL(buf[--cpos]) != FALSE) { ttputc('\b'); ttputc(' '); ttputc('\b'); --ttcol; } epos--; } while ((cpos > 0) && ISWORD(buf[cpos - 1])) { ttputc('\b'); ttputc(' '); ttputc('\b'); --ttcol; if (ISCTRL(buf[--cpos]) != FALSE) { ttputc('\b'); ttputc(' '); ttputc('\b'); --ttcol; } epos--; } ttflush(); break; case CCHR('\\'): case CCHR('Q'): /* quote next */ c = getkey(FALSE); /* FALLTHROUGH */ default: if (dynbuf && epos + 1 >= nbuf) { void *newp; size_t newsize = epos + epos + 16; if ((newp = realloc(buf, newsize)) == NULL) goto memfail; buf = newp; nbuf = newsize; } if (!dynbuf && epos + 1 >= nbuf) { ewprintf("Line too long"); return (emptyval); } for (i = epos; i > cpos; i--) buf[i] = buf[i - 1]; buf[cpos++] = (char)c; epos++; eputc((char)c); cc = ttcol; rr = ttrow; for (i = cpos; i < epos; i++) eputc(buf[i]); ttmove(rr, cc); ttflush(); } } done: if (cwin == TRUE) { /* blow away cpltion window */ bp = bfind("*Completions*", TRUE); if ((wp = popbuf(bp, WEPHEM)) != NULL) { if (wp->w_flag & WEPHEM) { curwp = wp; delwind(FFRAND, 1); } else { killbuffer(bp); } } } return (ret); memfail: if (dynbuf && buf) free(buf); ewprintf("Out of memory"); return (emptyval); }
int main (int argc, char *argv[]) { BUFFER *bp; char bname[NBUFN]; /* buffer name of file to read */ int c, f, n; int ffile; /* first file flag */ int carg; /* current arg to scan */ if (argc == 2 && 0 == strcmp("--version", argv[1])) { printf("%s\n", version); exit(0); } /* initialize the editor and process the startup file */ getwinsize(); /* find out the "real" screen size */ strncpy (bname, "*scratch*", 10); /* default buffer name */ edinit (bname); /* Buffers, windows */ vtinit (); /* Displays */ ffile = TRUE; /* no file to edit yet */ update (); /* let the user know we are here */ /* scan through the command line and get the files to edit */ for (carg = 1; carg < argc; ++carg) { /* set up a buffer for this file */ makename (bname, argv[carg]); /* if this is the first file, read it in */ if (ffile) { bp = curbp; makename (bname, argv[carg]); strncpy (bp->b_bname, bname, NBUFN); strncpy (bp->b_fname, argv[carg], NFILEN); if (readin (argv[carg]) == ABORT) { strncpy (bp->b_bname, "main", 5); strncpy (bp->b_fname, "", 1); } bp->b_dotp = bp->b_linep; bp->b_doto = 0; ffile = FALSE; } else { /* set this to inactive */ bp = bfind (bname, TRUE, 0); strncpy (bp->b_fname, argv[carg], NFILEN); bp->b_active = FALSE; } } /* setup to process commands */ lastflag = 0; /* Fake last flags */ curwp->w_flag |= WFMODE; /* and force an update */ loop: update (); /* Fix up the screen */ c = getkey (TRUE); if (mpresf != FALSE) { mlerase (); update (); } f = FALSE; n = 1; if (c == (CTRL | 'X')) /* ^X is a prefix */ c = CTLX | getctl (); if (kbdmip != NULL) { /* Save macro strokes */ if (c != (CTLX | ')') && kbdmip > &kbdm[NKBDM - 6]) { ctrlg (FALSE, 0); goto loop; } if (f != FALSE) { *kbdmip++ = (CTRL | 'U'); *kbdmip++ = n; } *kbdmip++ = c; } execute (c, f, n); /* Do it */ goto loop; }
/* ARGSUSED */ int queryrepl(int f, int n) { int s; int rcnt = 0; /* replacements made so far */ int plen; /* length of found string */ char news[NPAT], *rep; /* replacement string */ #ifndef NO_MACRO if (macrodef) { ewprintf("Can't query replace in macro"); return (FALSE); } #endif /* !NO_MACRO */ if ((s = readpattern("Query replace")) != TRUE) return (s); if ((rep = eread("Query replace %s with: ", news, NPAT, EFNUL | EFNEW | EFCR, pat)) == NULL) return (ABORT); else if (rep[0] == '\0') news[0] = '\0'; ewprintf("Query replacing %s with %s:", pat, news); plen = strlen(pat); /* * Search forward repeatedly, checking each time whether to insert * or not. The "!" case makes the check always true, so it gets put * into a tighter loop for efficiency. */ while (forwsrch() == TRUE) { retry: update(); switch (getkey(FALSE)) { case 'y': case ' ': if (lreplace((RSIZE)plen, news) == FALSE) return (FALSE); rcnt++; break; case '.': if (lreplace((RSIZE)plen, news) == FALSE) return (FALSE); rcnt++; goto stopsearch; /* ^G, CR or ESC */ case CCHR('G'): (void)ctrlg(FFRAND, 0); goto stopsearch; case CCHR('['): case CCHR('M'): goto stopsearch; case '!': do { if (lreplace((RSIZE)plen, news) == FALSE) return (FALSE); rcnt++; } while (forwsrch() == TRUE); goto stopsearch; case 'n': case CCHR('H'): /* To not replace */ case CCHR('?'): break; default: ewprintf("y/n or <SP>/<DEL>: replace/don't, [.] repl-end, [!] repl-rest, <CR>/<ESC> quit"); goto retry; } } stopsearch: curwp->w_rflag |= WFFULL; update(); if (rcnt == 1) ewprintf("Replaced 1 occurrence"); else ewprintf("Replaced %d occurrences", rcnt); return (TRUE); }
/* * Incremental Search. * dir is used as the initial direction to search. * ^S switch direction to forward * ^R switch direction to reverse * ^Q quote next character (allows searching for ^N etc.) * <ESC> exit from Isearch * <DEL> undoes last character typed. (tricky job to do this correctly). * other ^ exit search, don't set mark * else accumulate into search string */ static int isearch(int dir) { struct line *clp; /* Saved line pointer */ int c; int cbo; /* Saved offset */ int success; int pptr; int firstc; int xcase; int i; char opat[NPAT]; int cdotline; /* Saved line number */ #ifndef NO_MACRO if (macrodef) { ewprintf("Can't isearch in macro"); return (FALSE); } #endif /* !NO_MACRO */ for (cip = 0; cip < NSRCH; cip++) cmds[cip].s_code = SRCH_NOPR; (void)strlcpy(opat, pat, sizeof(opat)); cip = 0; pptr = -1; clp = curwp->w_dotp; cbo = curwp->w_doto; cdotline = curwp->w_dotline; is_lpush(); is_cpush(SRCH_BEGIN); success = TRUE; is_prompt(dir, TRUE, success); for (;;) { update(); switch (c = getkey(FALSE)) { case CCHR('['): /* * If new characters come in the next 300 msec, * we can assume that they belong to a longer * escaped sequence so we should ungetkey the * ESC to avoid writing out garbage. */ if (ttwait(300) == FALSE) ungetkey(c); srch_lastdir = dir; curwp->w_markp = clp; curwp->w_marko = cbo; curwp->w_markline = cdotline; ewprintf("Mark set"); return (TRUE); case CCHR('G'): if (success != TRUE) { while (is_peek() == SRCH_ACCM) is_undo(&pptr, &dir); success = TRUE; is_prompt(dir, pptr < 0, success); break; } curwp->w_dotp = clp; curwp->w_doto = cbo; curwp->w_dotline = cdotline; curwp->w_rflag |= WFMOVE; srch_lastdir = dir; (void)ctrlg(FFRAND, 0); (void)strlcpy(pat, opat, sizeof(pat)); return (ABORT); case CCHR('S'): if (dir == SRCH_BACK) { dir = SRCH_FORW; is_lpush(); is_cpush(SRCH_FORW); success = TRUE; } if (success == FALSE && dir == SRCH_FORW) { /* wrap the search to beginning */ curwp->w_dotp = bfirstlp(curbp); curwp->w_doto = 0; curwp->w_dotline = 1; if (is_find(dir) != FALSE) { is_cpush(SRCH_MARK); success = TRUE; } ewprintf("Overwrapped I-search: %s", pat); break; } is_lpush(); pptr = strlen(pat); (void)forwchar(FFRAND, 1); if (is_find(SRCH_FORW) != FALSE) is_cpush(SRCH_MARK); else { (void)backchar(FFRAND, 1); ttbeep(); success = FALSE; ewprintf("Failed I-search: %s", pat); } is_prompt(dir, pptr < 0, success); break; case CCHR('R'): if (dir == SRCH_FORW) { dir = SRCH_BACK; is_lpush(); is_cpush(SRCH_BACK); success = TRUE; } if (success == FALSE && dir == SRCH_BACK) { /* wrap the search to end */ curwp->w_dotp = blastlp(curbp); curwp->w_doto = llength(curwp->w_dotp); curwp->w_dotline = curwp->w_bufp->b_lines; if (is_find(dir) != FALSE) { is_cpush(SRCH_MARK); success = TRUE; } ewprintf("Overwrapped I-search: %s", pat); break; } is_lpush(); pptr = strlen(pat); (void)backchar(FFRAND, 1); if (is_find(SRCH_BACK) != FALSE) is_cpush(SRCH_MARK); else { (void)forwchar(FFRAND, 1); ttbeep(); success = FALSE; } is_prompt(dir, pptr < 0, success); break; case CCHR('W'): /* add the rest of the current word to the pattern */ clp = curwp->w_dotp; cbo = curwp->w_doto; firstc = 1; if (pptr == -1) pptr = 0; if (dir == SRCH_BACK) { /* when isearching backwards, cbo is the start of the pattern */ cbo += pptr; } /* if the search is case insensitive, add to pattern using lowercase */ xcase = 0; for (i = 0; pat[i]; i++) if (ISUPPER(CHARMASK(pat[i]))) xcase = 1; while (cbo < llength(clp)) { c = lgetc(clp, cbo++); if ((!firstc && !isalnum(c))) break; if (pptr == NPAT - 1) { ttbeep(); break; } firstc = 0; if (!xcase && ISUPPER(c)) c = TOLOWER(c); pat[pptr++] = c; pat[pptr] = '\0'; /* cursor only moves when isearching forwards */ if (dir == SRCH_FORW) { curwp->w_doto = cbo; curwp->w_rflag |= WFMOVE; update(); } } is_prompt(dir, pptr < 0, success); break; case CCHR('H'): case CCHR('?'): is_undo(&pptr, &dir); if (is_peek() != SRCH_ACCM) success = TRUE; is_prompt(dir, pptr < 0, success); break; case CCHR('\\'): case CCHR('Q'): c = (char)getkey(FALSE); goto addchar; case CCHR('M'): c = CCHR('J'); goto addchar; default: if (ISCTRL(c)) { ungetkey(c); curwp->w_markp = clp; curwp->w_marko = cbo; curwp->w_markline = cdotline; ewprintf("Mark set"); curwp->w_rflag |= WFMOVE; return (TRUE); } /* FALLTHRU */ case CCHR('I'): case CCHR('J'): addchar: if (pptr == -1) pptr = 0; if (pptr == 0) success = TRUE; if (pptr == NPAT - 1) ttbeep(); else { pat[pptr++] = c; pat[pptr] = '\0'; } is_lpush(); if (success != FALSE) { if (is_find(dir) != FALSE) is_cpush(c); else { success = FALSE; ttbeep(); is_cpush(SRCH_ACCM); } } else is_cpush(SRCH_ACCM); is_prompt(dir, FALSE, success); } } /* NOTREACHED */ }
static void PerformEditCommand( void *theEnv) { register int c; register int f; register int n; register int mflag; register int rtn_flag; char bname[NBUFN]; int num_a; char *fileName = NULL; DATA_OBJECT arg_ptr; /*====================*/ /* Get the file name. */ /*====================*/ if ((num_a = EnvArgCountCheck(theEnv,"edit",NO_MORE_THAN,1)) == -1) return; if (num_a == 1) { if (EnvArgTypeCheck(theEnv,"edit",1,SYMBOL_OR_STRING,&arg_ptr) == FALSE) return; fileName = DOToString(arg_ptr); } if(bheadp == NULL) { /**********************************************/ /* Initial entry, set up buffers and pointers */ /**********************************************/ genstrcpy(bname, "main"); /* Work out the name of */ if (num_a > 0) /* the default buffer. */ makename(bname,fileName); edinit(theEnv,bname); /* Buffers, windows. */ vtinit(theEnv); /* Displays. */ if (num_a > 0) { update(); /* You have to update */ readin(theEnv,fileName); /* in case "[New file]" */ } init_cmp_router(theEnv); /* Prepare the compile */ EnvDeactivateRouter(theEnv,"cmp_router"); /* router. */ } else { /**********************************************************/ /* Return from temporary exit, reset necessary stuff only */ /**********************************************************/ (*term.t_open)(); if (num_a > 0) { filevisit_guts(theEnv,fileName); } } sgarbf = TRUE; /* Force screen update */ lastbufn[0] = '\0'; /* Make sure last name */ /* is cleared out */ lastflag = 0; /* Fake last flags. */ loop: update(); /* Fix up the screen */ c = getkey(); if (mpresf != FALSE) { mlerase(); update(); if (c == ' ') /* ITS EMACS does this */ goto loop; } f = FALSE; n = 1; if (c == (COTL|'U')) { /* ^U, start argument */ f = TRUE; n = 4; /* with argument of 4 */ mflag = 0; /* that can be discarded. */ mlwrite("Arg: 4"); while ((((c=getkey()) >='0') && (c<='9')) || (c==(COTL|'U')) || (c=='-')){ if (c == (COTL|'U')) n = n*4; /* * If dash, and start of argument string, set arg. * to -1. Otherwise, insert it. */ else if (c == '-') { if (mflag) break; n = 0; mflag = -1; } /* * If first digit entered, replace previous argument * with digit and set sign. Otherwise, append to arg. */ else { if (!mflag) { n = 0; mflag = 1; } n = 10*n + c - '0'; } mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1)); } /* * Make arguments preceded by a minus sign negative and change * the special argument "^U -" to an effective "^U -1". */ if (mflag == -1) { if (n == 0) n++; n = -n; } } if (c == (COTL|'X')) /* ^X is a prefix */ c = CTLX | getctl(); if (kbdmip != NULL) { /* Save macro strokes. */ if (c!=(CTLX|')') && kbdmip>&kbdm[NKBDM-6]) { ctrlg(theEnv,FALSE, 0); goto loop; } if (f != FALSE) { *kbdmip++ = (COTL|'U'); *kbdmip++ = n; } *kbdmip++ = c; } rtn_flag = execute(theEnv,c, f, n); /* Do it. */ if(rtn_flag == EXIT) return; else goto loop; }
int meUndo(int f, int n) { if(n < -1) { #ifndef NDEBUG if(n == -4) { meUndoNode *nn ; FILE *undoFp=NULL ; if(undoFp == NULL) undoFp = fopen("undo.log","w+") ; fprintf(undoFp,"[Undo stack for %s]\n",frameCur->bufferCur->name) ; nn=frameCur->bufferCur->undoHead ; while(nn != NULL) { if(meUndoIsLineSort(nn)) { fprintf(undoFp,"Undo 0x%02x %p %ld %ld:",nn->type,nn->next, nn->udata.lineSort[0],nn->count) ; for(n=0 ; n<nn->count ; n++) fprintf(undoFp," %ld",nn->udata.lineSort[n+1]) ; fprintf(undoFp,"\n") ; } #if MEOPT_NARROW else if(meUndoIsNarrow(nn)) { meUndoNarrow *nun = (meUndoNarrow *) nn ; fprintf(undoFp,"Undo 0x%02x %p Nrrw %x %ld %ld %d [%s]\n",nun->type,nun->next, nun->name,nun->count,nun->udata.dotp,nun->markupCmd,nun->str) ; } #endif else { fprintf(undoFp,"Undo 0x%02x %p %ld (%ld,%d) [%s]\n",nn->type,nn->next,nn->count, nn->udata.dotp,nn->doto,nn->str) ; if(meUndoIsReplace(nn)) { for(n=0 ; n<nn->doto ; n++) fprintf(undoFp,"(%d,%d) ",nn->udata.pos[n][0],nn->udata.pos[n][1]) ; fprintf(undoFp,"\n") ; } } nn = nn->next ; } fprintf(undoFp,"---------------\n") ; fflush(undoFp) ; } else #endif undoContFlag++ ; } else if(!meModeTest(frameCur->bufferCur->mode,MDUNDO)) return ctrlg(meFALSE,1) ; else if(n < 0) meUndoRemove(frameCur->bufferCur) ; else { static meUndoNode *cun ; static meInt ccount ; static meUShort cdoto ; if((lastflag != meCFUNDO) && ((cun = frameCur->bufferCur->undoHead) != NULL)) { cdoto = cun->doto ; ccount = cun->count ; } for(;;) { meInt count, cont ; if((cun == NULL) || ((n <= 0) && !meModeTest(frameCur->bufferCur->mode,MDEDIT))) break ; if(bufferSetEdit() <= 0) /* Check we can change the buffer */ return meABORT ; cont=0 ; if(cun->type & meUNDO_SPECIAL) { if(meUndoIsSetEdit(cun)) { if(!(cun->type & meUNDO_UNSET_EDIT)) { autowriteremove(frameCur->bufferCur) ; meModeClear(frameCur->bufferCur->mode,MDEDIT) ; frameAddModeToWindows(WFMODE) ; /* update ALL mode lines */ } } else if(meUndoIsLineSort(cun)) { meLine *ln, *eln, **list ; meInt *lineSort, *undoInfo, dddd ; lineSort = cun->udata.lineSort ; windowGotoLine(meTRUE,(*lineSort++) + 1) ; if((list = meMalloc(cun->count * sizeof(meLine *))) == NULL) return meABORT ; undoInfo = meUndoAddLineSort(cun->count) ; eln = frameCur->windowCur->dotLine ; ln = meLineGetPrev(eln) ; for(count=0 ; count<cun->count ; eln=meLineGetNext(eln),count++) { list[*lineSort++] = eln ; eln->prev = (meLine *) count ; } for(count=0 ; count<cun->count ; ln=meLineGetNext(ln),count++) { if(undoInfo != NULL) { dddd = (meInt) list[count]->prev ; *undoInfo++ = dddd ; } ln->next = list[count] ; list[count]->prev = ln ; } ln->next = eln ; eln->prev = ln ; frameCur->windowCur->dotLine = list[0] ; meFree(list) ; } #if MEOPT_NARROW else if(meUndoIsNarrow(cun)) { meUndoNarrow *nun = (meUndoNarrow *) cun ; meInt name ; name = nun->name ; windowGotoLine(meTRUE,nun->udata.dotp+1) ; if(nun->type & meUNDO_NARROW_ADD) { meNarrow *nrrw ; nrrw = frameCur->bufferCur->narrow ; while(nrrw->name != name) nrrw = nrrw->next ; frameCur->bufferCur->dotLine = frameCur->windowCur->dotLine ; frameCur->bufferCur->dotLineNo = frameCur->windowCur->dotLineNo ; frameCur->bufferCur->dotOffset = 0 ; meBufferRemoveNarrow(frameCur->bufferCur,nrrw, (nun->markupCmd > 0) ? nun->str:NULL,1) ; } else { meLine *slp ; slp = frameCur->windowCur->dotLine ; windowGotoLine(meTRUE,ccount+1) ; meBufferCreateNarrow(frameCur->bufferCur,slp,frameCur->windowCur->dotLine, nun->udata.dotp,ccount,name,nun->scheme, (nun->markupFlag) ? nun->str:NULL,nun->markupCmd,1) ; } } #endif if(cun->type & meUNDO_CONTINUE) cont=1 ; goto meUndoNext ; } if(cun->type & meUNDO_REPLACE) { windowGotoLine(meTRUE,cun->udata.pos[cdoto-1][0]+1) ; count = cun->udata.pos[cdoto-1][1] ; if(count < 0) { cont = 1 ; count = -1 - count ; } frameCur->windowCur->dotOffset = (meUShort) count ; } else { if(cun->type & meUNDO_CONTINUE) cont = 1 ; windowGotoLine(meTRUE,cun->udata.dotp+1) ; frameCur->windowCur->dotOffset = cdoto ; } if(cun->type & meUNDO_SINGLE) { ccount-- ; count = 1 ; } else count = ccount ; if(cun->type & meUNDO_INSERT) { meWindowBackwardChar(frameCur->windowCur,count) ; if((count == 1)) meUndoAddDelChar() ; else meUndoAddDelChars(count) ; mldelete(count,NULL) ; } if(cun->type & meUNDO_DELETE) { /* When dealing with long lines this loop becomes infinitly * long because of the number of times that the line is * re-allocated - pre-allocate the line length first. In order * to reduce the processing overhead then we find the longest * strings and then add them back in in one go, this ensures * that we only ever re-allocate the line once. * Jon - 99/12/12. */ meUByte *ss, cc ; ss = cun->str ; /* Deal with a single character undo */ if(cun->type & meUNDO_SINGLE) { ss += ccount ; if((cc = *ss++) == meCHAR_NL) lineInsertNewline(meBUFINSFLAG_UNDOCALL); else if (cc != '\0') lineInsertChar(1, cc); meUndoAddInsChar() ; } else { /* Deal with a multiple character undo. */ count = bufferInsertText(ss,meBUFINSFLAG_UNDOCALL) ; if(count > 0) meUndoAddInsChars(count) ; } } if((cun->type & meUNDO_SINGLE) && (ccount > 0)) { if(cun->type & meUNDO_FORWARD) cdoto++ ; else if(cun->type & meUNDO_INSERT) cdoto-- ; } else if(cun->type & meUNDO_REPLACE) { cdoto-- ; if(!cdoto) goto meUndoNext ; } else { meUndoNext: if((cun = cun->next) != NULL) { cdoto = cun->doto ; ccount = cun->count ; } } if(!cont && (--n == 0)) break ; } thisflag = meCFUNDO ; } return meTRUE ; }
int main(int argc, char *argv[]) { BUFFER *bp; char bname[NBUFN]; /* buffer name of file to read */ int c, f, n, mflag; int ffile; /* first file flag */ int basec; /* c stripped of meta character */ /* initialize the editor and process the startup file */ getwinsize(); /* find out the "real" screen size */ strncpy(bname, "main", 5); /* default buffer name */ edinit(bname); /* Buffers, windows */ vtinit(); /* Displays */ ffile = TRUE; /* no file to edit yet */ update(); /* let the user know we are here */ /* scan through the command line and get the files to edit */ if (argc > 2) { (void) fprintf(stderr, "Can only edit one file at a time\n"); exit(1); } else if (argc == 2) { /* set up a buffer for this file */ makename(bname, argv[1]); /* if this is the first file, read it in */ if (ffile) { bp = curbp; makename(bname, argv[1]); strncpy(bp->b_bname, bname, NBUFN); strncpy(bp->b_fname, argv[1], NFILEN); if (readin(argv[1]) == ABORT) { strncpy(bp->b_bname, "main", 5); strncpy(bp->b_fname, "", 1); } bp->b_dotp = bp->b_linep; bp->b_doto = 0; ffile = FALSE; } else { /* set this to inactive */ bp = bfind(bname, TRUE, 0); strncpy(bp->b_fname, argv[1], NFILEN); bp->b_active = FALSE; } } /* setup to process commands */ lastflag = 0; /* Fake last flags */ curwp->w_flag |= WFMODE; /* and force an update */ loop: update(); /* Fix up the screen */ c = getkey(); if (mpresf != FALSE) { mlerase(); update(); } f = FALSE; n = 1; /* do META-# processing if needed */ basec = c & ~META; /* strip meta char off if there */ if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) { f = TRUE; /* there is a # arg */ n = 0; /* start with a zero default */ mflag = 1; /* current minus flag */ c = basec; /* strip the META */ while ((c >= '0' && c <= '9') || (c == '-')) { if (c == '-') { /* already hit a minus or digit? */ if ((mflag == -1) || (n != 0)) break; mflag = -1; } else n = n * 10 + (c - '0'); if ((n == 0) && (mflag == -1)) /* lonely - */ mlwrite("Arg:"); else mlwrite("Arg: %d", n * mflag); c = getkey(); /* get the next key */ } n = n * mflag; /* figure in the sign */ } /* do ^U repeat argument processing */ if (c == (CTRL | 'U')) { /* ^U, start argument */ f = TRUE; n = 4; /* with argument of 4 */ mflag = 0; /* that can be discarded */ mlwrite("Arg: 4"); while (((c = getkey ()) >= '0') && ((c <= '9') || (c == (CTRL | 'U')) || (c == '-'))) { if (c == (CTRL | 'U')) n = n * 4; /* * If dash, and start of argument string, set arg. * to -1. Otherwise, insert it. */ else if (c == '-') { if (mflag) break; n = 0; mflag = -1; } /* * If first digit entered, replace previous argument * with digit and set sign. Otherwise, append to arg. */ else { if (!mflag) { n = 0; mflag = 1; } n = 10 * n + c - '0'; } mlwrite("Arg: %d", (mflag >= 0) ? n : (n ? -n : -1)); } /* * Make arguments preceded by a minus sign negative and change * the special argument "^U -" to an effective "^U -1". */ if (mflag == -1) { if (n == 0) n++; n = -n; } } if (c == (CTRL | 'X')) /* ^X is a prefix */ c = CTLX | getctl (); if (kbdmip != NULL) { /* Save macro strokes */ if (c != (CTLX | ')') && kbdmip > &kbdm[NKBDM - 6]) { ctrlg(FALSE, 0); goto loop; } if (f != FALSE) { *kbdmip++ = (CTRL | 'U'); *kbdmip++ = n; } *kbdmip++ = c; } execute(c, f, n); /* Do it */ goto loop; }
/* ARGSUSED */ int re_queryrepl(int f, int n) { int rcnt = 0; /* replacements made so far */ int plen, s; /* length of found string */ char news[NPAT]; /* replacement string */ if ((s = re_readpattern("RE Query replace")) != TRUE) return (s); if (eread("Query replace %s with: ", news, NPAT, EFNUL | EFNEW | EFCR, re_pat) == NULL) return (ABORT); ewprintf("Query replacing %s with %s:", re_pat, news); /* * Search forward repeatedly, checking each time whether to insert * or not. The "!" case makes the check always true, so it gets put * into a tighter loop for efficiency. */ while (re_forwsrch() == TRUE) { retry: update(); switch (getkey(FALSE)) { case ' ': plen = regex_match[0].rm_eo - regex_match[0].rm_so; if (re_doreplace((RSIZE)plen, news) == FALSE) return (FALSE); rcnt++; break; case '.': plen = regex_match[0].rm_eo - regex_match[0].rm_so; if (re_doreplace((RSIZE)plen, news) == FALSE) return (FALSE); rcnt++; goto stopsearch; case CCHR('G'): /* ^G */ (void)ctrlg(FFRAND, 0); goto stopsearch; case CCHR('['): /* ESC */ case '`': goto stopsearch; case '!': do { plen = regex_match[0].rm_eo - regex_match[0].rm_so; if (re_doreplace((RSIZE)plen, news) == FALSE) return (FALSE); rcnt++; } while (re_forwsrch() == TRUE); goto stopsearch; case CCHR('?'): /* To not replace */ break; default: ewprintf("<SP> replace, [.] rep-end, <DEL> don't, [!] repl rest <ESC> quit"); goto retry; } } stopsearch: curwp->w_rflag |= WFFULL; update(); if (!inmacro) { if (rcnt == 0) ewprintf("(No replacements done)"); else if (rcnt == 1) ewprintf("(1 replacement done)"); else ewprintf("(%d replacements done)", rcnt); } return (TRUE); }