From: andy Date: Wed, 5 Sep 2012 08:13:59 +0000 (+1200) Subject: Getting close to a basic working readline now. X-Git-Url: https://pd.if.org/git/?p=pd_readline;a=commitdiff_plain;h=4bb27266f935c9aafad6870ffc8847fc65c8120f Getting close to a basic working readline now. --- diff --git a/.history b/.history deleted file mode 100644 index aa10a34..0000000 --- a/.history +++ /dev/null @@ -1,17 +0,0 @@ -ls -git add . -git commit -a -m "Added a C version of the editor." -git push origin master -cd pdeditor -./pdeditor -cd pdeditor -./pdeditor -mkdir foo -make -f makefile -clear -./struct_array -cd struct_array -python -cd struct_array -./struct_array - diff --git a/Notes_and_ideas.txt b/Notes_and_ideas.txt deleted file mode 100644 index 1a367a4..0000000 --- a/Notes_and_ideas.txt +++ /dev/null @@ -1,13 +0,0 @@ - - **** A Public Domain readline and command-history utility **** - - Random thoughts, comments ideas on doing a PD readline and -command-history utility. - -Keyboard operation - Keyboard determines characters sent to -computer. Chars are stored in keyboard buffer and then sent. -***NOTE*** - set up editable copy of kbd buffer? - -Keyboard scancodes - make and break codes. - - diff --git a/README b/README index 9e5f397..9442b26 100644 --- a/README +++ b/README @@ -1,32 +1,31 @@ ***** README - pd_readline ***** - This repo is for the (eventual) storage of a public-domain + This repo is for the storage of a public-domain readline-and-command-history implementation. -Update - 26th Aug 2012 - +Update - 5th Sep 2012 - -Very useful progress. -Keystroke sequences are now stored in an array of structs. -This makes it VERY easy to see the various special flags -in a keystroke sequence -(e.g. Esc, Ctrl, Alt and so on..... ). +Almost there! +The code now "pretty much" works as expected. +( However, pressing Enter exits the program rather +than storing the existing command-line and "staying +in the program". I hope to fix this soon. ) -Big breakthrough - the code can now distinguish between -normal "printable" keys and keys that should not be -printed (e.g. arrow keys, Ctrl sequences and so on). +You can edit a command-line (using backspace). +You can move around with left and right-arrow +keys. +Command-history can be recalled from a file with +the up-arrow key, and you can scroll up and down +through the command-history. -The next goal is to make the code move the cursor to the -left (when left-arrow is pressed) and delete a char (when -backspace is pressed). +*** CAUTION! *** - There is, however, an occasional +problem with "stack-smashing". -Still some way to go to get to a REAL readline, but we are -"on the way......" This code is released to the public domain. "Share and enjoy........ ;) " - - mooseman diff --git a/keyhandler.c b/keyhandler.c deleted file mode 100644 index af0eb76..0000000 --- a/keyhandler.c +++ /dev/null @@ -1,165 +0,0 @@ - - -/* keyhandler.c */ - -/* - A simple program to handle keys (in particular, function keys, - Ctrl keys, Alt keys and arrow keys). - This code is released to the public domain. - "Share and enjoy...." ;) -*/ - - -#include -#include -#include -#include -#include - - -void func1(void) -{ - printf("Hey, you entered foo! \n"); -} - -void func2(void) -{ - printf("Hey, you entered bar! \n"); -} - -void alt_a(void) -{ - printf("Hey, you pressed ALT a! \n"); -} - -void alt_b(void) -{ - printf("Hey, you pressed ALT b! \n"); -} - -void ctrl_a(void) -{ - printf("Hey, you pressed CTRL a! \n"); -} - -void ctrl_g(void) -{ - printf("Hey, you pressed CTRL g! \n"); -} - -void up_arrow(void) -{ - printf("Hey, you pressed the up arrow! \n"); -} - -void down_arrow(void) -{ - printf("Hey, you pressed the down arrow! \n"); -} - -void left_arrow(void) -{ - printf("Hey, you pressed the left arrow! \n"); -} - -void right_arrow(void) -{ - printf("Hey, you pressed the right arrow! \n"); -} - -void f2(void) -{ - printf("Hey, you pressed F2! \n"); -} - -void f3(void) -{ - printf("Hey, you pressed F3! \n"); -} - -void f4(void) -{ - printf("Hey, you pressed F4! \n"); -} - - - - -int main(void) -{ - - char word[80]; - char ch; - - do { - puts("Enter some text :"); - scanf("%s", word); - - if ( !strcmp(word, "foo") ) { - func1(); - } - - else if (!strcmp(word, "bar") ) { - func2(); - } - - else if (!strcmp(word, "\x1b\x61") ) { - alt_a(); - } - - else if (!strcmp(word, "\x1b\x62") ) { - alt_b(); - } - - else if (!strcmp(word, "\x07") ) { - ctrl_g(); - } - - else if (!strcmp(word, "\x01") ) { - ctrl_a(); - } - - else if (!strcmp(word, "\x1b\x5b\x41") ) { - up_arrow(); - } - - else if (!strcmp(word, "\x1b\x5b\x42") ) { - down_arrow(); - } - - else if (!strcmp(word, "\x1b\x5b\x43") ) { - right_arrow(); - } - - else if (!strcmp(word, "\x1b\x5b\x44") ) { - left_arrow(); - } - - else if (!strcmp(word, "\x1b\x4f\x51") ) { - f2(); - } - - else if (!strcmp(word, "\x1b\x4f\x52") ) { - f3(); - } - - else if (!strcmp(word, "\x1b\x4f\x53") ) { - f4(); - } - - else { - printf("Nope - I do not recognise that phrase.... \n"); - } - - printf("Try again? (y/n) : "); - scanf(" %c%*c", &ch); - } - - while( toupper(ch) != 'N' ); - - return 0; - -} - - - diff --git a/mg/Makefile b/mg/Makefile deleted file mode 100644 index 5b235e5..0000000 --- a/mg/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# $OpenBSD: Makefile,v 1.27 2012/06/18 07:13:26 jasper Exp $ - -PROG= mg - -LDADD+= -lcurses -lutil -DPADD+= ${LIBCURSES} ${LIBUTIL} - -# (Common) compile-time options: -# -# FKEYS -- add support for function key sequences. -# REGEX -- create regular expression functions. -# STARTUP -- look for and handle initialization file. -# XKEYS -- use termcap function key definitions. -# note: XKEYS and bsmap mode do _not_ get along. -# -CFLAGS+=-Wall -DFKEYS -DREGEX -DXKEYS - -SRCS= autoexec.c basic.c buffer.c cinfo.c dir.c display.c \ - echo.c extend.c file.c fileio.c funmap.c help.c kbd.c keymap.c \ - line.c macro.c main.c match.c modes.c paragraph.c random.c \ - re_search.c region.c search.c spawn.c tty.c ttyio.c ttykbd.c \ - undo.c version.c window.c word.c yank.c - -# -# More or less standalone extensions. -# -SRCS+= cmode.c cscope.c dired.c grep.c tags.c theo.c - -afterinstall: - ${INSTALL} -d ${DESTDIR}${DOCDIR}/mg - ${INSTALL} -m ${DOCMODE} -c ${.CURDIR}/tutorial \ - ${DESTDIR}${DOCDIR}/mg - - diff --git a/mg/autoexec.c b/mg/autoexec.c deleted file mode 100644 index ad3b08d..0000000 --- a/mg/autoexec.c +++ /dev/null @@ -1,111 +0,0 @@ -/* $OpenBSD: autoexec.c,v 1.14 2007/02/08 21:40:03 kjell Exp $ */ -/* this file is in the public domain */ -/* Author: Vincent Labrecque April 2002 */ - -#include "def.h" -#include "funmap.h" - -#include - -struct autoexec { - SLIST_ENTRY(autoexec) next; /* link in the linked list */ - const char *pattern; /* Pattern to match to filenames */ - PF fp; -}; - -static SLIST_HEAD(, autoexec) autos; -static int ready; - - -#define AUTO_GROW 8 -/* - * Return a NULL terminated array of function pointers to be called - * when we open a file that matches . The list must be free(ed) - * after use. - */ -PF * -find_autoexec(const char *fname) -{ - PF *pfl, *npfl; - int have, used; - struct autoexec *ae; - - if (!ready) - return (NULL); - - pfl = NULL; - have = 0; - used = 0; - SLIST_FOREACH(ae, &autos, next) { - if (fnmatch(ae->pattern, fname, 0) == 0) { - if (used >= have) { - npfl = realloc(pfl, (have + AUTO_GROW + 1) * - sizeof(PF)); - if (npfl == NULL) - panic("out of memory"); - pfl = npfl; - have += AUTO_GROW; - } - pfl[used++] = ae->fp; - } - } - if (used) - pfl[used] = NULL; - - return (pfl); -} - -int -add_autoexec(const char *pattern, const char *func) -{ - PF fp; - struct autoexec *ae; - - if (!ready) { - SLIST_INIT(&autos); - ready = 1; - } - fp = name_function(func); - if (fp == NULL) - return (FALSE); - ae = malloc(sizeof(*ae)); - if (ae == NULL) - return (FALSE); - ae->fp = fp; - ae->pattern = strdup(pattern); - if (ae->pattern == NULL) { - free(ae); - return (FALSE); - } - SLIST_INSERT_HEAD(&autos, ae, next); - - return (TRUE); -} - -/* - * Register an auto-execute hook; that is, specify a filename pattern - * (conforming to the shell's filename globbing rules) and an associated - * function to execute when a file matching the specified pattern - * is read into a buffer. -*/ -/* ARGSUSED */ -int -auto_execute(int f, int n) -{ - char patbuf[128], funcbuf[128], *patp, *funcp; - int s; - - if ((patp = eread("Filename pattern: ", patbuf, sizeof(patbuf), - EFNEW | EFCR)) == NULL) - return (ABORT); - else if (patp[0] == '\0') - return (FALSE); - if ((funcp = eread("Execute: ", funcbuf, sizeof(funcbuf), - EFNEW | EFCR | EFFUNC)) == NULL) - return (ABORT); - else if (funcp[0] == '\0') - return (FALSE); - if ((s = add_autoexec(patp, funcp)) != TRUE) - return (s); - return (TRUE); -} diff --git a/mg/basic.c b/mg/basic.c deleted file mode 100644 index 160d9c1..0000000 --- a/mg/basic.c +++ /dev/null @@ -1,532 +0,0 @@ -/* $OpenBSD: basic.c,v 1.37 2012/06/18 09:26:03 lum Exp $ */ - -/* This file is in the public domain */ - -/* - * Basic cursor motion commands. - * - * The routines in this file are the basic - * command functions for moving the cursor around on - * the screen, setting mark, and swapping dot with - * mark. Only moves between lines, which might make the - * current buffer framing bad, are hard. - */ -#include "def.h" - -#include - -/* - * Go to beginning of line. - */ -/* ARGSUSED */ -int -gotobol(int f, int n) -{ - curwp->w_doto = 0; - return (TRUE); -} - -/* - * Move cursor backwards. Do the - * right thing if the count is less than - * 0. Error if you try to move back from - * the beginning of the buffer. - */ -/* ARGSUSED */ -int -backchar(int f, int n) -{ - struct line *lp; - - if (n < 0) - return (forwchar(f, -n)); - while (n--) { - if (curwp->w_doto == 0) { - if ((lp = lback(curwp->w_dotp)) == curbp->b_headp) { - if (!(f & FFRAND)) - ewprintf("Beginning of buffer"); - return (FALSE); - } - curwp->w_dotp = lp; - curwp->w_doto = llength(lp); - curwp->w_rflag |= WFMOVE; - curwp->w_dotline--; - } else - curwp->w_doto--; - } - return (TRUE); -} - -/* - * Go to end of line. - */ -/* ARGSUSED */ -int -gotoeol(int f, int n) -{ - curwp->w_doto = llength(curwp->w_dotp); - return (TRUE); -} - -/* - * Move cursor forwards. Do the - * right thing if the count is less than - * 0. Error if you try to move forward - * from the end of the buffer. - */ -/* ARGSUSED */ -int -forwchar(int f, int n) -{ - if (n < 0) - return (backchar(f, -n)); - while (n--) { - if (curwp->w_doto == llength(curwp->w_dotp)) { - curwp->w_dotp = lforw(curwp->w_dotp); - if (curwp->w_dotp == curbp->b_headp) { - curwp->w_dotp = lback(curwp->w_dotp); - if (!(f & FFRAND)) - ewprintf("End of buffer"); - return (FALSE); - } - curwp->w_doto = 0; - curwp->w_dotline++; - curwp->w_rflag |= WFMOVE; - } else - curwp->w_doto++; - } - return (TRUE); -} - -/* - * Go to the beginning of the - * buffer. Setting WFFULL is conservative, - * but almost always the case. - */ -int -gotobob(int f, int n) -{ - (void) setmark(f, n); - curwp->w_dotp = bfirstlp(curbp); - curwp->w_doto = 0; - curwp->w_rflag |= WFFULL; - curwp->w_dotline = 1; - return (TRUE); -} - -/* - * Go to the end of the buffer. Leave dot 3 lines from the bottom of the - * window if buffer length is longer than window length; same as emacs. - * Setting WFFULL is conservative, but almost always the case. - */ -int -gotoeob(int f, int n) -{ - struct line *lp; - - (void) setmark(f, n); - curwp->w_dotp = blastlp(curbp); - curwp->w_doto = llength(curwp->w_dotp); - curwp->w_dotline = curwp->w_bufp->b_lines; - - lp = curwp->w_dotp; - n = curwp->w_ntrows - 3; - - if (n < curwp->w_bufp->b_lines && n >= 3) { - while (n--) - curwp->w_dotp = lback(curwp->w_dotp); - - curwp->w_linep = curwp->w_dotp; - curwp->w_dotp = lp; - } - curwp->w_rflag |= WFFULL; - return (TRUE); -} - -/* - * Move forward by full lines. - * If the number of lines to move is less - * than zero, call the backward line function to - * actually do it. The last command controls how - * the goal column is set. - */ -/* ARGSUSED */ -int -forwline(int f, int n) -{ - struct line *dlp; - - if (n < 0) - return (backline(f | FFRAND, -n)); - if ((dlp = curwp->w_dotp) == curbp->b_headp) - return(TRUE); - if ((lastflag & CFCPCN) == 0) /* Fix goal. */ - setgoal(); - thisflag |= CFCPCN; - if (n == 0) - return (TRUE); - while (n--) { - dlp = lforw(dlp); - if (dlp == curbp->b_headp) { - curwp->w_dotp = lback(dlp); - curwp->w_doto = llength(curwp->w_dotp); - curwp->w_rflag |= WFMOVE; - return (TRUE); - } - curwp->w_dotline++; - } - curwp->w_rflag |= WFMOVE; - curwp->w_dotp = dlp; - curwp->w_doto = getgoal(dlp); - - return (TRUE); -} - -/* - * This function is like "forwline", but - * goes backwards. The scheme is exactly the same. - * Check for arguments that are less than zero and - * call your alternate. Figure out the new line and - * call "movedot" to perform the motion. - */ -/* ARGSUSED */ -int -backline(int f, int n) -{ - struct line *dlp; - - if (n < 0) - return (forwline(f | FFRAND, -n)); - if ((lastflag & CFCPCN) == 0) /* Fix goal. */ - setgoal(); - thisflag |= CFCPCN; - dlp = curwp->w_dotp; - while (n-- && lback(dlp) != curbp->b_headp) { - dlp = lback(dlp); - curwp->w_dotline--; - } - curwp->w_dotp = dlp; - curwp->w_doto = getgoal(dlp); - curwp->w_rflag |= WFMOVE; - return (TRUE); -} - -/* - * Set the current goal column, which is saved in the external variable - * "curgoal", to the current cursor column. The column is never off - * the edge of the screen; it's more like display then show position. - */ -void -setgoal(void) -{ - curgoal = getcolpos(); /* Get the position. */ - /* we can now display past end of display, don't chop! */ -} - -/* - * This routine looks at a line (pointed - * to by the LINE pointer "dlp") and the current - * vertical motion goal column (set by the "setgoal" - * routine above) and returns the best offset to use - * when a vertical motion is made into the line. - */ -int -getgoal(struct line *dlp) -{ - int c, i, col = 0; - char tmp[5]; - - - for (i = 0; i < llength(dlp); i++) { - c = lgetc(dlp, i); - if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif - ) { - col |= 0x07; - col++; - } else if (ISCTRL(c) != FALSE) { - col += 2; - } else if (isprint(c)) - col++; - else { - col += snprintf(tmp, sizeof(tmp), "\\%o", c); - } - if (col > curgoal) - break; - } - return (i); -} - -/* - * Scroll forward by a specified number - * of lines, or by a full page if no argument. - * The "2" is the window overlap (this is the default - * value from ITS EMACS). Because the top line in - * the window is zapped, we have to do a hard - * update and get it back. - */ -/* ARGSUSED */ -int -forwpage(int f, int n) -{ - struct line *lp; - - if (!(f & FFARG)) { - n = curwp->w_ntrows - 2; /* Default scroll. */ - if (n <= 0) /* Forget the overlap */ - n = 1; /* if tiny window. */ - } else if (n < 0) - return (backpage(f | FFRAND, -n)); - - lp = curwp->w_linep; - while (n--) - if ((lp = lforw(lp)) == curbp->b_headp) { - ttbeep(); - ewprintf("End of buffer"); - return(TRUE); - } - - curwp->w_linep = lp; - curwp->w_rflag |= WFFULL; - - /* if in current window, don't move dot */ - for (n = curwp->w_ntrows; n-- && lp != curbp->b_headp; lp = lforw(lp)) - if (lp == curwp->w_dotp) - return (TRUE); - - /* Advance the dot the slow way, for line nos */ - while (curwp->w_dotp != curwp->w_linep) { - curwp->w_dotp = lforw(curwp->w_dotp); - curwp->w_dotline++; - } - curwp->w_doto = 0; - return (TRUE); -} - -/* - * This command is like "forwpage", - * but it goes backwards. The "2", like above, - * is the overlap between the two windows. The - * value is from the ITS EMACS manual. The - * hard update is done because the top line in - * the window is zapped. - */ -/* ARGSUSED */ -int -backpage(int f, int n) -{ - struct line *lp, *lp2; - - if (!(f & FFARG)) { - n = curwp->w_ntrows - 2; /* Default scroll. */ - if (n <= 0) /* Don't blow up if the */ - return (backline(f, 1));/* window is tiny. */ - } else if (n < 0) - return (forwpage(f | FFRAND, -n)); - - lp = lp2 = curwp->w_linep; - - while (n-- && lback(lp) != curbp->b_headp) { - lp = lback(lp); - } - if (lp == curwp->w_linep) { - ttbeep(); - ewprintf("Beginning of buffer"); - } - curwp->w_linep = lp; - curwp->w_rflag |= WFFULL; - - /* if in current window, don't move dot */ - for (n = curwp->w_ntrows; n-- && lp != curbp->b_headp; lp = lforw(lp)) - if (lp == curwp->w_dotp) - return (TRUE); - - lp2 = lforw(lp2); - - /* Move the dot the slow way, for line nos */ - while (curwp->w_dotp != lp2) { - if (curwp->w_dotline <= curwp->w_ntrows) - return (TRUE); - curwp->w_dotp = lback(curwp->w_dotp); - curwp->w_dotline--; - } - curwp->w_doto = 0; - return (TRUE); -} - -/* - * These functions are provided for compatibility with Gosling's Emacs. They - * are used to scroll the display up (or down) one line at a time. - */ -int -forw1page(int f, int n) -{ - if (!(f & FFARG)) { - n = 1; - f = FFUNIV; - } - forwpage(f | FFRAND, n); - return (TRUE); -} - -int -back1page(int f, int n) -{ - if (!(f & FFARG)) { - n = 1; - f = FFUNIV; - } - backpage(f | FFRAND, n); - return (TRUE); -} - -/* - * Page the other window. Check to make sure it exists, then - * nextwind, forwpage and restore window pointers. - */ -int -pagenext(int f, int n) -{ - struct mgwin *wp; - - if (wheadp->w_wndp == NULL) { - ewprintf("No other window"); - return (FALSE); - } - wp = curwp; - (void) nextwind(f, n); - (void) forwpage(f, n); - curwp = wp; - curbp = wp->w_bufp; - return (TRUE); -} - -/* - * Internal set mark routine, used by other functions (daveb). - */ -void -isetmark(void) -{ - curwp->w_markp = curwp->w_dotp; - curwp->w_marko = curwp->w_doto; - curwp->w_markline = curwp->w_dotline; -} - -/* - * Set the mark in the current window - * to the value of dot. A message is written to - * the echo line. (ewprintf knows about macros) - */ -/* ARGSUSED */ -int -setmark(int f, int n) -{ - isetmark(); - ewprintf("Mark set"); - return (TRUE); -} - -/* Clear the mark, if set. */ -/* ARGSUSED */ -int -clearmark(int f, int n) -{ - if (!curwp->w_markp) - return (FALSE); - - curwp->w_markp = NULL; - curwp->w_marko = 0; - curwp->w_markline = 0; - - return (TRUE); -} - -/* - * Swap the values of "dot" and "mark" in - * the current window. This is pretty easy, because - * all of the hard work gets done by the standard routine - * that moves the mark about. The only possible - * error is "no mark". - */ -/* ARGSUSED */ -int -swapmark(int f, int n) -{ - struct line *odotp; - int odoto, odotline; - - if (curwp->w_markp == NULL) { - ewprintf("No mark in this window"); - return (FALSE); - } - odotp = curwp->w_dotp; - odoto = curwp->w_doto; - odotline = curwp->w_dotline; - curwp->w_dotp = curwp->w_markp; - curwp->w_doto = curwp->w_marko; - curwp->w_dotline = curwp->w_markline; - curwp->w_markp = odotp; - curwp->w_marko = odoto; - curwp->w_markline = odotline; - curwp->w_rflag |= WFMOVE; - return (TRUE); -} - -/* - * Go to a specific line, mostly for - * looking up errors in C programs, which give the - * error a line number. If an argument is present, then - * it is the line number, else prompt for a line number - * to use. - */ -/* ARGSUSED */ -int -gotoline(int f, int n) -{ - struct line *clp; - char buf[32], *bufp; - const char *err; - - if (!(f & FFARG)) { - if ((bufp = eread("Goto line: ", buf, sizeof(buf), - EFNUL | EFNEW | EFCR)) == NULL) - return (ABORT); - if (bufp[0] == '\0') - return (ABORT); - n = (int)strtonum(buf, INT_MIN, INT_MAX, &err); - if (err) { - ewprintf("Line number %s", err); - return (FALSE); - } - } - if (n >= 0) { - if (n == 0) - n++; - curwp->w_dotline = n; - clp = lforw(curbp->b_headp); /* "clp" is first line */ - while (--n > 0) { - if (lforw(clp) == curbp->b_headp) { - curwp->w_dotline = curwp->w_bufp->b_lines; - break; - } - clp = lforw(clp); - } - } else { - curwp->w_dotline = curwp->w_bufp->b_lines + n; - clp = lback(curbp->b_headp); /* "clp" is last line */ - while (n < 0) { - if (lback(clp) == curbp->b_headp) { - curwp->w_dotline = 1; - break; - } - clp = lback(clp); - n++; - } - } - curwp->w_dotp = clp; - curwp->w_doto = 0; - curwp->w_rflag |= WFMOVE; - return (TRUE); -} diff --git a/mg/buffer.c b/mg/buffer.c deleted file mode 100644 index 0a4254c..0000000 --- a/mg/buffer.c +++ /dev/null @@ -1,863 +0,0 @@ -/* $OpenBSD: buffer.c,v 1.78 2012/03/14 13:56:35 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Buffer handling. - */ - -#include "def.h" -#include "kbd.h" /* needed for modes */ - -#include -#include - -static struct buffer *makelist(void); -static struct buffer *bnew(const char *); - -static int usebufname(const char *); - -/* Flag for global working dir */ -extern int globalwd; - -/* ARGSUSED */ -int -togglereadonly(int f, int n) -{ - int s; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (!(curbp->b_flag & BFREADONLY)) - curbp->b_flag |= BFREADONLY; - else { - curbp->b_flag &= ~BFREADONLY; - if (curbp->b_flag & BFCHG) - ewprintf("Warning: Buffer was modified"); - } - curwp->w_rflag |= WFMODE; - - return (TRUE); -} - -/* Switch to the named buffer. - * If no name supplied, switch to the default (alternate) buffer. - */ -int -usebufname(const char *bufp) -{ - struct buffer *bp; - - if (bufp == NULL) - return (ABORT); - if (bufp[0] == '\0' && curbp->b_altb != NULL) - bp = curbp->b_altb; - else if ((bp = bfind(bufp, TRUE)) == NULL) - return (FALSE); - - /* and put it in current window */ - curbp = bp; - return (showbuffer(bp, curwp, WFFRAME | WFFULL)); -} - -/* - * Attach a buffer to a window. The values of dot and mark come - * from the buffer if the use count is 0. Otherwise, they come - * from some other window. *scratch* is the default alternate - * buffer. - */ -/* ARGSUSED */ -int -usebuffer(int f, int n) -{ - char bufn[NBUFN], *bufp; - - /* Get buffer to use from user */ - if ((curbp->b_altb == NULL) && - ((curbp->b_altb = bfind("*scratch*", TRUE)) == NULL)) - bufp = eread("Switch to buffer: ", bufn, NBUFN, EFNEW | EFBUF); - else - bufp = eread("Switch to buffer: (default %s) ", bufn, NBUFN, - EFNUL | EFNEW | EFBUF, curbp->b_altb->b_bname); - - return (usebufname(bufp)); -} - -/* - * pop to buffer asked for by the user. - */ -/* ARGSUSED */ -int -poptobuffer(int f, int n) -{ - struct buffer *bp; - struct mgwin *wp; - char bufn[NBUFN], *bufp; - - /* Get buffer to use from user */ - if ((curbp->b_altb == NULL) && - ((curbp->b_altb = bfind("*scratch*", TRUE)) == NULL)) - bufp = eread("Switch to buffer in other window: ", bufn, NBUFN, - EFNEW | EFBUF); - else - bufp = eread("Switch to buffer in other window: (default %s) ", - bufn, NBUFN, EFNUL | EFNEW | EFBUF, curbp->b_altb->b_bname); - if (bufp == NULL) - return (ABORT); - if (bufp[0] == '\0' && curbp->b_altb != NULL) - bp = curbp->b_altb; - else if ((bp = bfind(bufn, TRUE)) == NULL) - return (FALSE); - if (bp == curbp) - return (splitwind(f, n)); - /* and put it in a new, non-ephemeral window */ - if ((wp = popbuf(bp, WNONE)) == NULL) - return (FALSE); - curbp = bp; - curwp = wp; - return (TRUE); -} - -/* - * Dispose of a buffer, by name. - * Ask for the name. Look it up (don't get too - * upset if it isn't there at all!). Clear the buffer (ask - * if the buffer has been changed). Then free the header - * line and the buffer header. Bound to "C-X k". - */ -/* ARGSUSED */ -int -killbuffer_cmd(int f, int n) -{ - struct buffer *bp; - char bufn[NBUFN], *bufp; - - if ((bufp = eread("Kill buffer: (default %s) ", bufn, NBUFN, - EFNUL | EFNEW | EFBUF, curbp->b_bname)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - bp = curbp; - else if ((bp = bfind(bufn, FALSE)) == NULL) - return (FALSE); - return (killbuffer(bp)); -} - -int -killbuffer(struct buffer *bp) -{ - struct buffer *bp1; - struct buffer *bp2; - struct mgwin *wp; - int s; - struct undo_rec *rec, *next; - - /* - * Find some other buffer to display. Try the alternate buffer, - * then the first different buffer in the buffer list. If there's - * only one buffer, create buffer *scratch* and make it the alternate - * buffer. Return if *scratch* is only buffer... - */ - if ((bp1 = bp->b_altb) == NULL) { - bp1 = (bp == bheadp) ? bp->b_bufp : bheadp; - if (bp1 == NULL) { - /* only one buffer. see if it's *scratch* */ - if (bp == bfind("*scratch*", FALSE)) - return (TRUE); - /* create *scratch* for alternate buffer */ - if ((bp1 = bfind("*scratch*", TRUE)) == NULL) - return (FALSE); - } - } - if ((s = bclear(bp)) != TRUE) - return (s); - for (wp = wheadp; bp->b_nwnd > 0; wp = wp->w_wndp) { - if (wp->w_bufp == bp) { - bp2 = bp1->b_altb; /* save alternate buffer */ - if (showbuffer(bp1, wp, WFMODE | WFFRAME | WFFULL)) - bp1->b_altb = bp2; - else - bp1 = bp2; - } - } - if (bp == curbp) - curbp = bp1; - free(bp->b_headp); /* Release header line. */ - bp2 = NULL; /* Find the header. */ - bp1 = bheadp; - while (bp1 != bp) { - if (bp1->b_altb == bp) - bp1->b_altb = (bp->b_altb == bp1) ? NULL : bp->b_altb; - bp2 = bp1; - bp1 = bp1->b_bufp; - } - bp1 = bp1->b_bufp; /* Next one in chain. */ - if (bp2 == NULL) /* Unlink it. */ - bheadp = bp1; - else - bp2->b_bufp = bp1; - while (bp1 != NULL) { /* Finish with altb's */ - if (bp1->b_altb == bp) - bp1->b_altb = (bp->b_altb == bp1) ? NULL : bp->b_altb; - bp1 = bp1->b_bufp; - } - rec = TAILQ_FIRST(&bp->b_undo); - - while (rec != NULL) { - next = TAILQ_NEXT(rec, next); - free_undo_record(rec); - rec = next; - } - - free(bp->b_bname); /* Release name block */ - free(bp); /* Release buffer block */ - return (TRUE); -} - -/* - * Save some buffers - just call anycb with the arg flag. - */ -/* ARGSUSED */ -int -savebuffers(int f, int n) -{ - if (anycb(f) == ABORT) - return (ABORT); - return (TRUE); -} - -/* - * Listing buffers. - */ -static int listbuf_ncol; - -static int listbuf_goto_buffer(int f, int n); -static int listbuf_goto_buffer_one(int f, int n); -static int listbuf_goto_buffer_helper(int f, int n, int only); - -static PF listbuf_pf[] = { - listbuf_goto_buffer -}; -static PF listbuf_one[] = { - listbuf_goto_buffer_one -}; - - -static struct KEYMAPE (2 + IMAPEXT) listbufmap = { - 2, - 2 + IMAPEXT, - rescan, - { - { - CCHR('M'), CCHR('M'), listbuf_pf, NULL - }, - { - '1', '1', listbuf_one, NULL - } - } -}; - -/* - * Display the buffer list. This is done - * in two parts. The "makelist" routine figures out - * the text, and puts it in a buffer. "popbuf" - * then pops the data onto the screen. Bound to - * "C-X C-B". - */ -/* ARGSUSED */ -int -listbuffers(int f, int n) -{ - static int initialized = 0; - struct buffer *bp; - struct mgwin *wp; - - if (!initialized) { - maps_add((KEYMAP *)&listbufmap, "listbufmap"); - initialized = 1; - } - - if ((bp = makelist()) == NULL || (wp = popbuf(bp, WNONE)) == NULL) - return (FALSE); - wp->w_dotp = bp->b_dotp; /* fix up if window already on screen */ - wp->w_doto = bp->b_doto; - bp->b_modes[0] = name_mode("fundamental"); - bp->b_modes[1] = name_mode("listbufmap"); - bp->b_nmodes = 1; - - return (TRUE); -} - -/* - * This routine rebuilds the text for the - * list buffers command. Return pointer - * to new list if everything works. - * Return NULL if there is an error (if - * there is no memory). - */ -static struct buffer * -makelist(void) -{ - int w = ncol / 2; - struct buffer *bp, *blp; - struct line *lp; - - if ((blp = bfind("*Buffer List*", TRUE)) == NULL) - return (NULL); - if (bclear(blp) != TRUE) - return (NULL); - blp->b_flag &= ~BFCHG; /* Blow away old. */ - blp->b_flag |= BFREADONLY; - - listbuf_ncol = ncol; /* cache ncol for listbuf_goto_buffer */ - - if (addlinef(blp, "%-*s%s", w, " MR Buffer", "Size File") == FALSE || - addlinef(blp, "%-*s%s", w, " -- ------", "---- ----") == FALSE) - return (NULL); - - for (bp = bheadp; bp != NULL; bp = bp->b_bufp) { - RSIZE nbytes; - - nbytes = 0; /* Count bytes in buf. */ - if (bp != blp) { - lp = bfirstlp(bp); - while (lp != bp->b_headp) { - nbytes += llength(lp) + 1; - lp = lforw(lp); - } - if (nbytes) - nbytes--; /* no bonus newline */ - } - - if (addlinef(blp, "%c%c%c %-*.*s%c%-6d %-*s", - (bp == curbp) ? '.' : ' ', /* current buffer ? */ - ((bp->b_flag & BFCHG) != 0) ? '*' : ' ', /* changed ? */ - ((bp->b_flag & BFREADONLY) != 0) ? ' ' : '*', - w - 5, /* four chars already written */ - w - 5, /* four chars already written */ - bp->b_bname, /* buffer name */ - strlen(bp->b_bname) < w - 5 ? ' ' : '$', /* truncated? */ - nbytes, /* buffer size */ - w - 7, /* seven chars already written */ - bp->b_fname) == FALSE) - return (NULL); - } - blp->b_dotp = bfirstlp(blp); /* put dot at beginning of - * buffer */ - blp->b_doto = 0; - return (blp); /* All done */ -} - -static int -listbuf_goto_buffer(int f, int n) -{ - return (listbuf_goto_buffer_helper(f, n, 0)); -} - -static int -listbuf_goto_buffer_one(int f, int n) -{ - return (listbuf_goto_buffer_helper(f, n, 1)); -} - -static int -listbuf_goto_buffer_helper(int f, int n, int only) -{ - struct buffer *bp; - struct mgwin *wp; - char *line = NULL; - int i, ret = FALSE; - - if (curwp->w_dotp->l_text[listbuf_ncol/2 - 1] == '$') { - ewprintf("buffer name truncated"); - return (FALSE); - } - - if ((line = malloc(listbuf_ncol/2)) == NULL) - return (FALSE); - - memcpy(line, curwp->w_dotp->l_text + 4, listbuf_ncol/2 - 5); - for (i = listbuf_ncol/2 - 6; i > 0; i--) { - if (line[i] != ' ') { - line[i + 1] = '\0'; - break; - } - } - if (i == 0) - goto cleanup; - - for (bp = bheadp; bp != NULL; bp = bp->b_bufp) { - if (strcmp(bp->b_bname, line) == 0) - break; - } - if (bp == NULL) - goto cleanup; - - if ((wp = popbuf(bp, WNONE)) == NULL) - goto cleanup; - curbp = bp; - curwp = wp; - - if (only) - ret = (onlywind(f, n)); - else - ret = TRUE; - -cleanup: - free(line); - - return (ret); -} - -/* - * The argument "fmt" points to a format string. Append this line to the - * buffer. Handcraft the EOL on the end. Return TRUE if it worked and - * FALSE if you ran out of room. - */ -int -addlinef(struct buffer *bp, char *fmt, ...) -{ - va_list ap; - struct line *lp; - - if ((lp = lalloc(0)) == NULL) - return (FALSE); - va_start(ap, fmt); - if (vasprintf(&lp->l_text, fmt, ap) == -1) { - lfree(lp); - va_end(ap); - return (FALSE); - } - lp->l_used = strlen(lp->l_text); - va_end(ap); - - bp->b_headp->l_bp->l_fp = lp; /* Hook onto the end */ - lp->l_bp = bp->b_headp->l_bp; - bp->b_headp->l_bp = lp; - lp->l_fp = bp->b_headp; - bp->b_lines++; - - return (TRUE); -} - -/* - * Look through the list of buffers, giving the user a chance to save them. - * Return TRUE if there are any changed buffers afterwards. Buffers that don't - * have an associated file don't count. Return FALSE if there are no changed - * buffers. Return ABORT if an error occurs or if the user presses c-g. - */ -int -anycb(int f) -{ - struct buffer *bp; - int s = FALSE, save = FALSE, ret; - char pbuf[NFILEN + 11]; - - for (bp = bheadp; bp != NULL; bp = bp->b_bufp) { - if (bp->b_fname != NULL && *(bp->b_fname) != '\0' && - (bp->b_flag & BFCHG) != 0) { - ret = snprintf(pbuf, sizeof(pbuf), "Save file %s", - bp->b_fname); - if (ret < 0 || ret >= sizeof(pbuf)) { - ewprintf("Error: filename too long!"); - return (ABORT); - } - if ((f == TRUE || (save = eyorn(pbuf)) == TRUE) && - buffsave(bp) == TRUE) { - bp->b_flag &= ~BFCHG; - upmodes(bp); - } else - s = TRUE; - if (save == ABORT) - return (save); - save = TRUE; - } - } - if (save == FALSE /* && kbdmop == NULL */ ) /* experimental */ - ewprintf("(No files need saving)"); - return (s); -} - -/* - * Search for a buffer, by name. - * If not found, and the "cflag" is TRUE, - * create a new buffer. Return pointer to the found - * (or new) buffer. - */ -struct buffer * -bfind(const char *bname, int cflag) -{ - struct buffer *bp; - - bp = bheadp; - while (bp != NULL) { - if (strcmp(bname, bp->b_bname) == 0) - return (bp); - bp = bp->b_bufp; - } - if (cflag != TRUE) - return (NULL); - - bp = bnew(bname); - - return (bp); -} - -/* - * Create a new buffer and put it in the list of - * all buffers. - */ -static struct buffer * -bnew(const char *bname) -{ - struct buffer *bp; - struct line *lp; - int i; - size_t len; - - bp = calloc(1, sizeof(struct buffer)); - if (bp == NULL) { - ewprintf("Can't get %d bytes", sizeof(struct buffer)); - return (NULL); - } - if ((lp = lalloc(0)) == NULL) { - free(bp); - return (NULL); - } - bp->b_altb = bp->b_bufp = NULL; - bp->b_dotp = lp; - bp->b_doto = 0; - bp->b_markp = NULL; - bp->b_marko = 0; - bp->b_flag = defb_flag; - /* if buffer name starts and ends with '*', we ignore changes */ - len = strlen(bname); - if (len) { - if (bname[0] == '*' && bname[len - 1] == '*') - bp->b_flag |= BFIGNDIRTY; - } - bp->b_nwnd = 0; - bp->b_headp = lp; - bp->b_nmodes = defb_nmodes; - TAILQ_INIT(&bp->b_undo); - bp->b_undoptr = NULL; - memset(&bp->b_undopos, 0, sizeof(bp->b_undopos)); - i = 0; - do { - bp->b_modes[i] = defb_modes[i]; - } while (i++ < defb_nmodes); - bp->b_fname[0] = '\0'; - bp->b_cwd[0] = '\0'; - bzero(&bp->b_fi, sizeof(bp->b_fi)); - lp->l_fp = lp; - lp->l_bp = lp; - bp->b_bufp = bheadp; - bheadp = bp; - bp->b_dotline = bp->b_markline = 1; - bp->b_lines = 1; - if ((bp->b_bname = strdup(bname)) == NULL) { - ewprintf("Can't get %d bytes", strlen(bname) + 1); - return (NULL); - } - - return (bp); -} - -/* - * This routine blows away all of the text - * in a buffer. If the buffer is marked as changed - * then we ask if it is ok to blow it away; this is - * to save the user the grief of losing text. The - * window chain is nearly always wrong if this gets - * called; the caller must arrange for the updates - * that are required. Return TRUE if everything - * looks good. - */ -int -bclear(struct buffer *bp) -{ - struct line *lp; - int s; - - /* Has buffer changed, and do we care? */ - if (!(bp->b_flag & BFIGNDIRTY) && (bp->b_flag & BFCHG) != 0 && - (s = eyesno("Buffer modified; kill anyway")) != TRUE) - return (s); - bp->b_flag &= ~BFCHG; /* Not changed */ - while ((lp = lforw(bp->b_headp)) != bp->b_headp) - lfree(lp); - bp->b_dotp = bp->b_headp; /* Fix dot */ - bp->b_doto = 0; - bp->b_markp = NULL; /* Invalidate "mark" */ - bp->b_marko = 0; - bp->b_dotline = bp->b_markline = 1; - bp->b_lines = 1; - - return (TRUE); -} - -/* - * Display the given buffer in the given window. Flags indicated - * action on redisplay. Update modified flag so insert loop can check it. - */ -int -showbuffer(struct buffer *bp, struct mgwin *wp, int flags) -{ - struct buffer *obp; - struct mgwin *owp; - - /* Ensure file has not been modified elsewhere */ - if (fchecktime(bp) != TRUE) - bp->b_flag |= BFDIRTY; - - if (wp->w_bufp == bp) { /* Easy case! */ - wp->w_rflag |= flags; - wp->w_dotp = bp->b_dotp; - wp->w_doto = bp->b_doto; - return (TRUE); - } - /* First, detach the old buffer from the window */ - if ((bp->b_altb = obp = wp->w_bufp) != NULL) { - if (--obp->b_nwnd == 0) { - obp->b_dotp = wp->w_dotp; - obp->b_doto = wp->w_doto; - obp->b_markp = wp->w_markp; - obp->b_marko = wp->w_marko; - obp->b_dotline = wp->w_dotline; - obp->b_markline = wp->w_markline; - } - } - /* Now, attach the new buffer to the window */ - wp->w_bufp = bp; - - if (bp->b_nwnd++ == 0) { /* First use. */ - wp->w_dotp = bp->b_dotp; - wp->w_doto = bp->b_doto; - wp->w_markp = bp->b_markp; - wp->w_marko = bp->b_marko; - wp->w_dotline = bp->b_dotline; - wp->w_markline = bp->b_markline; - } else - /* already on screen, steal values from other window */ - for (owp = wheadp; owp != NULL; owp = wp->w_wndp) - if (wp->w_bufp == bp && owp != wp) { - wp->w_dotp = owp->w_dotp; - wp->w_doto = owp->w_doto; - wp->w_markp = owp->w_markp; - wp->w_marko = owp->w_marko; - wp->w_dotline = owp->w_dotline; - wp->w_markline = owp->w_markline; - break; - } - wp->w_rflag |= WFMODE | flags; - return (TRUE); -} - -/* - * Augment a buffer name with a number, if necessary - * - * If more than one file of the same basename() is open, - * the additional buffers are named "file<2>", "file<3>", and - * so forth. This function adjusts a buffer name to - * include the number, if necessary. - */ -int -augbname(char *bn, const char *fn, size_t bs) -{ - int count; - size_t remain, len; - - if ((len = xbasename(bn, fn, bs)) >= bs) - return (FALSE); - - remain = bs - len; - for (count = 2; bfind(bn, FALSE) != NULL; count++) - snprintf(bn + len, remain, "<%d>", count); - - return (TRUE); -} - -/* - * Pop the buffer we got passed onto the screen. - * Returns a status. - */ -struct mgwin * -popbuf(struct buffer *bp, int flags) -{ - struct mgwin *wp; - - if (bp->b_nwnd == 0) { /* Not on screen yet. */ - /* - * Pick a window for a pop-up. - * If only one window, split the screen. - * Flag the new window as ephemeral - */ - if (wheadp->w_wndp == NULL && - splitwind(FFOTHARG, flags) == FALSE) - return (NULL); - - /* - * Pick the uppermost window that isn't - * the current window. An LRU algorithm - * might be better. Return a pointer, or NULL on error. - */ - wp = wheadp; - - while (wp != NULL && wp == curwp) - wp = wp->w_wndp; - } else - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) - if (wp->w_bufp == bp) { - wp->w_rflag |= WFFULL | WFFRAME; - return (wp); - } - if (showbuffer(bp, wp, WFFULL) != TRUE) - return (NULL); - return (wp); -} - -/* - * Insert another buffer at dot. Very useful. - */ -/* ARGSUSED */ -int -bufferinsert(int f, int n) -{ - struct buffer *bp; - struct line *clp; - int clo, nline; - char bufn[NBUFN], *bufp; - - /* Get buffer to use from user */ - if (curbp->b_altb != NULL) - bufp = eread("Insert buffer: (default %s) ", bufn, NBUFN, - EFNUL | EFNEW | EFBUF, curbp->b_altb->b_bname); - else - bufp = eread("Insert buffer: ", bufn, NBUFN, EFNEW | EFBUF); - if (bufp == NULL) - return (ABORT); - if (bufp[0] == '\0' && curbp->b_altb != NULL) - bp = curbp->b_altb; - else if ((bp = bfind(bufn, FALSE)) == NULL) - return (FALSE); - - if (bp == curbp) { - ewprintf("Cannot insert buffer into self"); - return (FALSE); - } - /* insert the buffer */ - nline = 0; - clp = bfirstlp(bp); - for (;;) { - for (clo = 0; clo < llength(clp); clo++) - if (linsert(1, lgetc(clp, clo)) == FALSE) - return (FALSE); - if ((clp = lforw(clp)) == bp->b_headp) - break; - if (newline(FFRAND, 1) == FALSE) /* fake newline */ - return (FALSE); - nline++; - } - if (nline == 1) - ewprintf("[Inserted 1 line]"); - else - ewprintf("[Inserted %d lines]", nline); - - clp = curwp->w_linep; /* cosmetic adjustment */ - if (curwp->w_dotp == clp) { /* for offscreen insert */ - while (nline-- && lback(clp) != curbp->b_headp) - clp = lback(clp); - curwp->w_linep = clp; /* adjust framing. */ - curwp->w_rflag |= WFFULL; - } - return (TRUE); -} - -/* - * Turn off the dirty bit on this buffer. - */ -/* ARGSUSED */ -int -notmodified(int f, int n) -{ - struct mgwin *wp; - - curbp->b_flag &= ~BFCHG; - wp = wheadp; /* Update mode lines. */ - while (wp != NULL) { - if (wp->w_bufp == curbp) - wp->w_rflag |= WFMODE; - wp = wp->w_wndp; - } - ewprintf("Modification-flag cleared"); - return (TRUE); -} - -/* - * Popbuf and set all windows to top of buffer. - */ -int -popbuftop(struct buffer *bp, int flags) -{ - struct mgwin *wp; - - bp->b_dotp = bfirstlp(bp); - bp->b_doto = 0; - if (bp->b_nwnd != 0) { - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) - if (wp->w_bufp == bp) { - wp->w_dotp = bp->b_dotp; - wp->w_doto = 0; - wp->w_rflag |= WFFULL; - } - } - return (popbuf(bp, flags) != NULL); -} - -/* - * Return the working directory for the current buffer, terminated - * with a '/'. First, try to extract it from the current buffer's - * filename. If that fails, use global cwd. - */ -int -getbufcwd(char *path, size_t plen) -{ - char cwd[NFILEN]; - - if (plen == 0) - return (FALSE); - - if (globalwd == FALSE && curbp->b_cwd[0] != '\0') { - (void)strlcpy(path, curbp->b_cwd, plen); - } else { - if (getcwdir(cwd, sizeof(cwd)) == FALSE) - goto error; - (void)strlcpy(path, cwd, plen); - } - return (TRUE); -error: - path[0] = '\0'; - return (FALSE); -} - -/* - * Ensures a buffer has not been modified elsewhere; e.g. on disk. - * Prompt the user if it has. - * Returns TRUE if it has NOT (i.e. buffer is ok to edit). - * FALSE or ABORT otherwise - */ -int -checkdirty(struct buffer *bp) -{ - int s; - - if ((bp->b_flag & (BFDIRTY | BFIGNDIRTY)) == BFDIRTY) { - if ((s = eyorn("File changed on disk; really edit the buffer")) - != TRUE) - return (s); - bp->b_flag &= ~BFDIRTY; - bp->b_flag |= BFIGNDIRTY; - } - - return (TRUE); -} - diff --git a/mg/chrdef.h b/mg/chrdef.h deleted file mode 100644 index ed94098..0000000 --- a/mg/chrdef.h +++ /dev/null @@ -1,81 +0,0 @@ -/* $OpenBSD: chrdef.h,v 1.7 2005/06/14 18:14:40 kjell Exp $ */ - -/* This file is in the public domain. */ - -/* - * sys/default/chardef.h: character set specific #defines for Mg 2a - * Warning: System specific ones exist - */ - -/* - * Casting should be at least as efficient as anding with 0xff, - * and won't have the size problems. Override in sysdef.h if no - * unsigned char type. - */ -#define CHARMASK(c) ((unsigned char) (c)) - -/* - * These flags, and the macros below them, - * make up a do-it-yourself set of "ctype" macros that - * understand the DEC multinational set, and let me ask - * a slightly different set of questions. - */ -#define _MG_W 0x01 /* Word. */ -#define _MG_U 0x02 /* Upper case letter. */ -#define _MG_L 0x04 /* Lower case letter. */ -#define _MG_C 0x08 /* Control. */ -#define _MG_P 0x10 /* end of sentence punctuation */ -#define _MG_D 0x20 /* is decimal digit */ - -#define ISWORD(c) ((cinfo[CHARMASK(c)]&_MG_W)!=0) -#define ISCTRL(c) ((cinfo[CHARMASK(c)]&_MG_C)!=0) -#define ISUPPER(c) ((cinfo[CHARMASK(c)]&_MG_U)!=0) -#define ISLOWER(c) ((cinfo[CHARMASK(c)]&_MG_L)!=0) -#define ISEOSP(c) ((cinfo[CHARMASK(c)]&_MG_P)!=0) -#define ISDIGIT(c) ((cinfo[CHARMASK(c)]&_MG_D)!=0) -#define TOUPPER(c) ((c)-0x20) -#define TOLOWER(c) ((c)+0x20) - -/* - * Generally useful thing for chars - */ -#define CCHR(x) ((x) ^ 0x40) /* CCHR('?') == DEL */ - -#ifndef METACH -#define METACH CCHR('[') -#endif - -#ifdef XKEYS -#define K00 256 -#define K01 257 -#define K02 258 -#define K03 259 -#define K04 260 -#define K05 261 -#define K06 262 -#define K07 263 -#define K08 264 -#define K09 265 -#define K0A 266 -#define K0B 267 -#define K0C 268 -#define K0D 269 -#define K0E 270 -#define K0F 271 -#define K10 272 -#define K11 273 -#define K12 274 -#define K13 275 -#define K14 276 -#define K15 277 -#define K16 278 -#define K17 279 -#define K18 280 -#define K19 281 -#define K1A 282 -#define K1B 283 -#define K1C 284 -#define K1D 285 -#define K1E 286 -#define K1F 287 -#endif diff --git a/mg/cinfo.c b/mg/cinfo.c deleted file mode 100644 index f568897..0000000 --- a/mg/cinfo.c +++ /dev/null @@ -1,154 +0,0 @@ -/* $OpenBSD: cinfo.c,v 1.16 2011/11/28 04:41:39 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Character class tables. - * Do it yourself character classification - * macros, that understand the multinational character set, - * and let me ask some questions the standard macros (in - * ctype.h) don't let you ask. - */ -#include "def.h" - -/* - * This table, indexed by a character drawn - * from the 256 member character set, is used by my - * own character type macros to answer questions about the - * type of a character. It handles the full multinational - * character set, and lets me ask some questions that the - * standard "ctype" macros cannot ask. - */ -/* - * Due to incompatible behaviour between "standard" emacs and - * ctags word traversing, '_' character's value is changed on - * the fly in ctags mode, hence non-const. - */ -char cinfo[256] = { - _MG_C, _MG_C, _MG_C, _MG_C, /* 0x0X */ - _MG_C, _MG_C, _MG_C, _MG_C, - _MG_C, _MG_C, _MG_C, _MG_C, - _MG_C, _MG_C, _MG_C, _MG_C, - _MG_C, _MG_C, _MG_C, _MG_C, /* 0x1X */ - _MG_C, _MG_C, _MG_C, _MG_C, - _MG_C, _MG_C, _MG_C, _MG_C, - _MG_C, _MG_C, _MG_C, _MG_C, - 0, _MG_P, 0, 0, /* 0x2X */ - _MG_W, _MG_W, 0, _MG_W, - 0, 0, 0, 0, - 0, 0, _MG_P, 0, - _MG_D | _MG_W, _MG_D | _MG_W, _MG_D | _MG_W, _MG_D | _MG_W, /* 0x3X */ - _MG_D | _MG_W, _MG_D | _MG_W, _MG_D | _MG_W, _MG_D | _MG_W, - _MG_D | _MG_W, _MG_D | _MG_W, 0, 0, - 0, 0, 0, _MG_P, - 0, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, /* 0x4X */ - _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, - _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, - _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, - _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, /* 0x5X */ - _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, - _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, 0, - 0, 0, 0, 0, - 0, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, /* 0x6X */ - _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, - _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, - _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, - _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, /* 0x7X */ - _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, - _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, 0, - 0, 0, 0, _MG_C, - 0, 0, 0, 0, /* 0x8X */ - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, /* 0x9X */ - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, /* 0xAX */ - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, /* 0xBX */ - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, /* 0xCX */ - _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, - _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, - _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, - 0, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, /* 0xDX */ - _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, - _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, _MG_U | _MG_W, - _MG_U | _MG_W, _MG_U | _MG_W, 0, _MG_W, - _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, /* 0xEX */ - _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, - _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, - _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, - 0, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, /* 0xFX */ - _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, - _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, _MG_L | _MG_W, - _MG_L | _MG_W, _MG_L | _MG_W, 0, 0 -}; - -/* - * Find the name of a keystroke. Needs to be changed to handle 8-bit printing - * characters and function keys better. Returns a pointer to the terminating - * '\0'. Returns NULL on failure. - */ -char * -getkeyname(char *cp, size_t len, int k) -{ - const char *np; - size_t copied; - - if (k < 0) - k = CHARMASK(k); /* sign extended char */ - switch (k) { - case CCHR('@'): - np = "C-SPC"; - break; - case CCHR('I'): - np = "TAB"; - break; - case CCHR('M'): - np = "RET"; - break; - case CCHR('['): - np = "ESC"; - break; - case ' ': - np = "SPC"; - break; /* yuck again */ - case CCHR('?'): - np = "DEL"; - break; - default: -#ifdef FKEYS - if (k >= KFIRST && k <= KLAST && - (np = keystrings[k - KFIRST]) != NULL) - break; -#endif - if (k > CCHR('?')) { - *cp++ = '0'; - *cp++ = ((k >> 6) & 7) + '0'; - *cp++ = ((k >> 3) & 7) + '0'; - *cp++ = (k & 7) + '0'; - *cp = '\0'; - return (cp); - } else if (k < ' ') { - *cp++ = 'C'; - *cp++ = '-'; - k = CCHR(k); - if (ISUPPER(k)) - k = TOLOWER(k); - } - *cp++ = k; - *cp = '\0'; - return (cp); - } - copied = strlcpy(cp, np, len); - if (copied >= len) - copied = len - 1; - return (cp + copied); -} diff --git a/mg/cmode.c b/mg/cmode.c deleted file mode 100644 index 674d89d..0000000 --- a/mg/cmode.c +++ /dev/null @@ -1,528 +0,0 @@ -/* $OpenBSD: cmode.c,v 1.8 2012/05/18 02:13:44 lum Exp $ */ -/* - * This file is in the public domain. - * - * Author: Kjell Wooding - */ - -/* - * Implement an non-irritating KNF-compliant mode for editing - * C code. - */ -#include - -#include "def.h" -#include "kbd.h" -#include "funmap.h" - -/* Pull in from modes.c */ -extern int changemode(int, int, char *); - -static int cc_strip_trailp = TRUE; /* Delete Trailing space? */ -static int cc_basic_indent = 8; /* Basic Indent multiple */ -static int cc_cont_indent = 4; /* Continued line indent */ -static int cc_colon_indent = -8; /* Label / case indent */ - -static int getmatch(int, int); -static int getindent(const struct line *, int *); -static int in_whitespace(struct line *, int); -static int findcolpos(const struct buffer *, const struct line *, int); -static struct line *findnonblank(struct line *); -static int isnonblank(const struct line *, int); - -void cmode_init(void); -int cc_comment(int, int); - -/* Keymaps */ - -static PF cmode_brace[] = { - cc_brace, /* } */ -}; - -static PF cmode_cCP[] = { - compile, /* C-c P */ -}; - - -static PF cmode_cc[] = { - NULL, /* ^C */ - rescan, /* ^D */ - rescan, /* ^E */ - rescan, /* ^F */ - rescan, /* ^G */ - rescan, /* ^H */ - cc_tab, /* ^I */ - rescan, /* ^J */ - rescan, /* ^K */ - rescan, /* ^L */ - cc_lfindent, /* ^M */ -}; - -static PF cmode_spec[] = { - cc_char, /* : */ -}; - -static struct KEYMAPE (1 + IMAPEXT) cmode_cmap = { - 1, - 1 + IMAPEXT, - rescan, - { - { 'P', 'P', cmode_cCP, NULL } - } -}; - -static struct KEYMAPE (3 + IMAPEXT) cmodemap = { - 3, - 3 + IMAPEXT, - rescan, - { - { CCHR('C'), CCHR('M'), cmode_cc, (KEYMAP *) &cmode_cmap }, - { ':', ':', cmode_spec, NULL }, - { '}', '}', cmode_brace, NULL } - } -}; - -/* Funtion, Mode hooks */ - -void -cmode_init(void) -{ - funmap_add(cmode, "c-mode"); - funmap_add(cc_char, "c-handle-special-char"); - funmap_add(cc_brace, "c-handle-special-brace"); - funmap_add(cc_tab, "c-tab-or-indent"); - funmap_add(cc_indent, "c-indent"); - funmap_add(cc_lfindent, "c-indent-and-newline"); - maps_add((KEYMAP *)&cmodemap, "c"); -} - -/* - * Enable/toggle c-mode - */ -int -cmode(int f, int n) -{ - return(changemode(f, n, "c")); -} - -/* - * Handle special C character - selfinsert then indent. - */ -int -cc_char(int f, int n) -{ - if (n < 0) - return (FALSE); - if (selfinsert(FFRAND, n) == FALSE) - return (FALSE); - return (cc_indent(FFRAND, n)); -} - -/* - * Handle special C character - selfinsert then indent. - */ -int -cc_brace(int f, int n) -{ - if (n < 0) - return (FALSE); - if (showmatch(FFRAND, 1) == FALSE) - return (FALSE); - return (cc_indent(FFRAND, n)); -} - - -/* - * If we are in the whitespace at the beginning of the line, - * simply act as a regular tab. If we are not, indent - * current line according to whitespace rules. - */ -int -cc_tab(int f, int n) -{ - int inwhitep = FALSE; /* In leading whitespace? */ - - inwhitep = in_whitespace(curwp->w_dotp, llength(curwp->w_dotp)); - - /* If empty line, or in whitespace */ - if (llength(curwp->w_dotp) == 0 || inwhitep) - return (selfinsert(f, n)); - - return (cc_indent(FFRAND, 1)); -} - -/* - * Attempt to indent current line according to KNF rules. - */ -int -cc_indent(int f, int n) -{ - int pi, mi; /* Previous indents */ - int ci, dci; /* current indent, don't care */ - struct line *lp; - int ret; - - if (n < 0) - return (FALSE); - - undo_boundary_enable(FFRAND, 0); - if (cc_strip_trailp) - deltrailwhite(FFRAND, 1); - - /* - * Search backwards for a non-blank, non-preprocessor, - * non-comment line - */ - - lp = findnonblank(curwp->w_dotp); - - pi = getindent(lp, &mi); - - /* Strip leading space on current line */ - delleadwhite(FFRAND, 1); - /* current indent is computed only to current position */ - dci = getindent(curwp->w_dotp, &ci); - - if (pi + ci < 0) - ret = indent(FFOTHARG, 0); - else - ret = indent(FFOTHARG, pi + ci); - - undo_boundary_enable(FFRAND, 1); - - return (ret); -} - -/* - * Indent-and-newline (technically, newline then indent) - */ -int -cc_lfindent(int f, int n) -{ - if (n < 0) - return (FALSE); - if (newline(FFRAND, 1) == FALSE) - return (FALSE); - return (cc_indent(FFRAND, n)); -} - -/* - * Get the level of indention after line lp is processed - * Note getindent has two returns: - * curi = value if indenting current line. - * return value = value affecting subsequent lines. - */ -static int -getindent(const struct line *lp, int *curi) -{ - int lo, co; /* leading space, current offset*/ - int nicol = 0; /* position count */ - int ccol = 0; /* current column */ - int c = '\0'; /* current char */ - int newind = 0; /* new index value */ - int stringp = FALSE; /* in string? */ - int escp = FALSE; /* Escape char? */ - int lastc = '\0'; /* Last matched string delimeter */ - int nparen = 0; /* paren count */ - int obrace = 0; /* open brace count */ - int cbrace = 0; /* close brace count */ - int contp = FALSE; /* Continue? */ - int firstnwsp = FALSE; /* First nonspace encountered? */ - int colonp = FALSE; /* Did we see a colon? */ - int questionp = FALSE; /* Did we see a question mark? */ - int slashp = FALSE; /* Slash? */ - int astp = FALSE; /* Asterisk? */ - int cpos = -1; /* comment position */ - int cppp = FALSE; /* Preprocessor command? */ - - *curi = 0; - - /* Compute leading space */ - for (lo = 0; lo < llength(lp); lo++) { - if (!isspace(c = lgetc(lp, lo))) - break; - if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif /* NOTAB */ - ) { - nicol |= 0x07; - } - nicol++; - } - - /* If last line was blank, choose 0 */ - if (lo == llength(lp)) - nicol = 0; - - newind = 0; - ccol = nicol; /* current column */ - /* Compute modifiers */ - for (co = lo; co < llength(lp); co++) { - c = lgetc(lp, co); - /* We have a non-whitespace char */ - if (!firstnwsp && !isspace(c)) { - contp = TRUE; - if (c == '#') - cppp = TRUE; - firstnwsp = TRUE; - } - if (c == '\\') - escp = !escp; - else if (stringp) { - if (!escp && (c == '"' || c == '\'')) { - /* unescaped string char */ - if (getmatch(c, lastc)) - stringp = FALSE; - } - } else if (c == '"' || c == '\'') { - stringp = TRUE; - lastc = c; - } else if (c == '(') { - nparen++; - } else if (c == ')') { - nparen--; - } else if (c == '{') { - obrace++; - firstnwsp = FALSE; - contp = FALSE; - } else if (c == '}') { - cbrace++; - } else if (c == '?') { - questionp = TRUE; - } else if (c == ':') { - /* ignore (foo ? bar : baz) construct */ - if (!questionp) - colonp = TRUE; - } else if (c == ';') { - if (nparen > 0) - contp = FALSE; - } else if (c == '/') { - /* first nonwhitespace? -> indent */ - if (firstnwsp) { - /* If previous char asterisk -> close */ - if (astp) - cpos = -1; - else - slashp = TRUE; - } - } else if (c == '*') { - /* If previous char slash -> open */ - if (slashp) - cpos = co; - else - astp = TRUE; - } else if (firstnwsp) { - firstnwsp = FALSE; - } - - /* Reset matches that apply to next character only */ - if (c != '\\') - escp = FALSE; - if (c != '*') - astp = FALSE; - if (c != '/') - slashp = FALSE; - } - /* - * If not terminated with a semicolon, and brace or paren open. - * we continue - */ - if (colonp) { - *curi += cc_colon_indent; - newind -= cc_colon_indent; - } - - *curi -= (cbrace) * cc_basic_indent; - newind += obrace * cc_basic_indent; - - if (nparen < 0) - newind -= cc_cont_indent; - else if (nparen > 0) - newind += cc_cont_indent; - - *curi += nicol; - - /* Ignore preprocessor. Otherwise, add current column */ - if (cppp) { - newind = nicol; - *curi = 0; - } else { - newind += nicol; - } - - if (cpos != -1) - newind = findcolpos(curbp, lp, cpos); - - return (newind); -} - -/* - * Given a delimeter and its purported mate, tell us if they - * match. - */ -static int -getmatch(int c, int mc) -{ - int match = FALSE; - - switch (c) { - case '"': - match = (mc == '"'); - break; - case '\'': - match = (mc == '\''); - break; - case '(': - match = (mc == ')'); - break; - case '[': - match = (mc == ']'); - break; - case '{': - match = (mc == '}'); - break; - } - - return (match); -} - -static int -in_whitespace(struct line *lp, int len) -{ - int lo; - int inwhitep = FALSE; - - for (lo = 0; lo < len; lo++) { - if (!isspace(lgetc(lp, lo))) - break; - if (lo == len - 1) - inwhitep = TRUE; - } - - return (inwhitep); -} - - -/* convert a line/offset pair to a column position (for indenting) */ -static int -findcolpos(const struct buffer *bp, const struct line *lp, int lo) -{ - int col, i, c; - char tmp[5]; - - /* determine column */ - col = 0; - - for (i = 0; i < lo; ++i) { - c = lgetc(lp, i); - if (c == '\t' -#ifdef NOTAB - && !(bp->b_flag & BFNOTAB) -#endif /* NOTAB */ - ) { - col |= 0x07; - col++; - } else if (ISCTRL(c) != FALSE) - col += 2; - else if (isprint(c)) { - col++; - } else { - col += snprintf(tmp, sizeof(tmp), "\\%o", c); - } - - } - return (col); -} - -/* - * Find a non-blank line, searching backwards from the supplied line pointer. - * For C, nonblank is non-preprocessor, non C++, and accounts - * for complete C-style comments. - */ -static struct line * -findnonblank(struct line *lp) -{ - int lo; - int nonblankp = FALSE; - int commentp = FALSE; - int slashp; - int astp; - int c; - - while (lback(lp) != curbp->b_headp && (commentp || !nonblankp)) { - lp = lback(lp); - slashp = FALSE; - astp = FALSE; - - /* Potential nonblank? */ - nonblankp = isnonblank(lp, llength(lp)); - - /* - * Search from end, removing complete C-style - * comments. If one is found, ignore it and - * test for nonblankness from where it starts. - */ - slashp = FALSE; - /* Scan backwards from end to find C-style comment */ - for (lo = llength(lp) - 1; lo >= 0; lo--) { - if (!isspace(c = lgetc(lp, lo))) { - if (commentp) { /* find comment "open" */ - if (c == '*') - astp = TRUE; - else if (astp && c == '/') { - commentp = FALSE; - /* whitespace to here? */ - nonblankp = isnonblank(lp, lo); - } - } else { /* find comment "close" */ - if (c == '/') - slashp = TRUE; - else if (slashp && c == '*') - /* found a comment */ - commentp = TRUE; - } - } - } - } - - /* Rewound to start of file? */ - if (lback(lp) == curbp->b_headp && !nonblankp) - return (curbp->b_headp); - - return (lp); -} - -/* - * Given a line, scan forward to 'omax' and determine if we - * are all C whitespace. - * Note that preprocessor directives and C++-style comments - * count as whitespace. C-style comments do not, and must - * be handled elsewhere. - */ -static int -isnonblank(const struct line *lp, int omax) -{ - int nonblankp = FALSE; /* Return value */ - int slashp = FALSE; /* Encountered slash */ - int lo; /* Loop index */ - int c; /* char being read */ - - /* Scan from front for preprocessor, C++ comments */ - for (lo = 0; lo < omax; lo++) { - if (!isspace(c = lgetc(lp, lo))) { - /* Possible nonblank line */ - nonblankp = TRUE; - /* skip // and # starts */ - if (c == '#' || (slashp && c == '/')) { - nonblankp = FALSE; - break; - } else if (!slashp && c == '/') { - slashp = TRUE; - continue; - } - } - slashp = FALSE; - } - return (nonblankp); -} diff --git a/mg/cscope.c b/mg/cscope.c deleted file mode 100644 index 9a8db5e..0000000 --- a/mg/cscope.c +++ /dev/null @@ -1,609 +0,0 @@ -/* $OpenBSD: cscope.c,v 1.3 2012/07/02 08:08:31 lum Exp $ */ - -/* - * This file is in the public domain. - * - * Author: Sunil Nimmagadda - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "def.h" - -#define CSSYMBOL 0 -#define CSDEFINITION 1 -#define CSCALLEDFUNCS 2 -#define CSCALLERFUNCS 3 -#define CSTEXT 4 -#define CSEGREP 6 -#define CSFINDFILE 7 -#define CSINCLUDES 8 - -struct cstokens { - const char *fname; - const char *function; - const char *lineno; - const char *pattern; -}; - -struct csmatch { - TAILQ_ENTRY(csmatch) entry; - int lineno; -}; - -struct csrecord { - TAILQ_ENTRY(csrecord) entry; - char *filename; - TAILQ_HEAD(matches, csmatch) matches; -}; - -static TAILQ_HEAD(csrecords, csrecord) csrecords = TAILQ_HEAD_INITIALIZER(csrecords); -static struct csrecord *addentryr; -static struct csrecord *currecord; -static struct csmatch *curmatch; -static const char *addentryfn; -static const char *csprompt[] = { - "Find this symbol: ", - "Find this global definition: ", - "Find functions called by this function: ", - "Find functions calling this function: ", - "Find this text string: ", - "Change this text string: ", - "Find this egrep pattern: ", - "Find this file: ", - "Find files #including this file: " -}; - -static int addentry(struct buffer *, char *); -static void csflush(void); -static int do_cscope(int); -static int csexists(const char *); -static int getattr(char *, struct cstokens *); -static int jumptomatch(void); -static void prettyprint(struct buffer *, struct cstokens *); -static const char *ltrim(const char *); - -/* - * Find this symbol. Bound to C-c s s - */ -/* ARGSUSED */ -int -cssymbol(int f, int n) -{ - return (do_cscope(CSSYMBOL)); -} - -/* - * Find this global definition. Bound to C-c s d - */ -/* ARGSUSED */int -csdefinition(int f, int n) -{ - return (do_cscope(CSDEFINITION)); -} - -/* - * Find functions called by this function. Bound to C-c s l - */ -/* ARGSUSED */ -int -csfuncalled(int f, int n) -{ - return (do_cscope(CSCALLEDFUNCS)); -} - -/* - * Find functions calling this function. Bound to C-c s c - */ -/* ARGSUSED */ -int -cscallerfuncs(int f, int n) -{ - return (do_cscope(CSCALLERFUNCS)); -} - -/* - * Find this text. Bound to C-c s t - */ -/* ARGSUSED */ -int -csfindtext(int f, int n) -{ - return (do_cscope(CSTEXT)); -} - -/* - * Find this egrep pattern. Bound to C-c s e - */ -/* ARGSUSED */ -int -csegrep(int f, int n) -{ - return (do_cscope(CSEGREP)); -} - -/* - * Find this file. Bound to C-c s f - */ -/* ARGSUSED */ -int -csfindfile(int f, int n) -{ - return (do_cscope(CSFINDFILE)); -} - -/* - * Find files #including this file. Bound to C-c s i - */ -/* ARGSUSED */ -int -csfindinc(int f, int n) -{ - return (do_cscope(CSINCLUDES)); -} - -/* - * Create list of files to index in the given directory - * using cscope-indexer. - */ -/* ARGSUSED */ -int -cscreatelist(int f, int n) -{ - struct buffer *bp; - struct stat sb; - FILE *fpipe; - char dir[NFILEN], cmd[BUFSIZ], title[BUFSIZ], *line, *bufp; - size_t len; - int clen; - - if (getbufcwd(dir, sizeof(dir)) == FALSE) - dir[0] = '\0'; - - bufp = eread("Index files in directory: ", dir, - sizeof(dir), EFCR | EFDEF | EFNEW | EFNUL); - - if (bufp == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - - if (stat(dir, &sb) == -1) { - ewprintf("stat: %s", strerror(errno)); - return (FALSE); - } else if (S_ISDIR(sb.st_mode) == 0) { - ewprintf("%s: Not a directory", dir); - return (FALSE); - } - - if (csexists("cscope-indexer") == FALSE) { - ewprintf("no such file or directory, cscope-indexer"); - return (FALSE); - } - - clen = snprintf(cmd, sizeof(cmd), "cscope-indexer -v %s", dir); - if (clen < 0 || clen >= sizeof(cmd)) - return (FALSE); - - if ((fpipe = popen(cmd, "r")) == NULL) { - ewprintf("problem opening pipe"); - return (FALSE); - } - - bp = bfind("*cscope*", TRUE); - if (bclear(bp) != TRUE) - return (FALSE); - bp->b_flag |= BFREADONLY; - - clen = snprintf(title, sizeof(title), "%s%s", - "Creating cscope file list 'cscope.files' in: ", dir); - if (clen < 0 || clen >= sizeof(title)) - return (FALSE); - addline(bp, title); - addline(bp, ""); - /* All lines are NUL terminated */ - while ((line = fgetln(fpipe, &len)) != NULL) { - line[len - 1] = '\0'; - addline(bp, line); - } - pclose(fpipe); - return (popbuftop(bp, WNONE)); -} - -/* - * Next Symbol. Bound to C-c s n - */ -/* ARGSUSED */ -int -csnextmatch(int f, int n) -{ - struct csrecord *r; - struct csmatch *m; - - if (curmatch == NULL) { - if ((r = TAILQ_FIRST(&csrecords)) == NULL) { - ewprintf("The *cscope* buffer does not exist yet"); - return (FALSE); - } - currecord = r; - curmatch = TAILQ_FIRST(&r->matches); - } else { - m = TAILQ_NEXT(curmatch, entry); - if (m == NULL) { - r = TAILQ_NEXT(currecord, entry); - if (r == NULL) { - ewprintf("The end of *cscope* buffer has been" - " reached"); - return (FALSE); - } else { - currecord = r; - curmatch = TAILQ_FIRST(&currecord->matches); - } - } else - curmatch = m; - } - return (jumptomatch()); -} - -/* - * Previous Symbol. Bound to C-c s p - */ -/* ARGSUSED */ -int -csprevmatch(int f, int n) -{ - struct csmatch *m; - struct csrecord *r; - - if (curmatch == NULL) - return (FALSE); - else { - m = TAILQ_PREV(curmatch, matches, entry); - if (m) - curmatch = m; - else { - r = TAILQ_PREV(currecord, csrecords, entry); - if (r == NULL) { - ewprintf("The beginning of *cscope* buffer has" - " been reached"); - return (FALSE); - } else { - currecord = r; - curmatch = TAILQ_LAST(&currecord->matches, - matches); - } - } - } - return (jumptomatch()); -} - -/* - * Next file. - */ -int -csnextfile(int f, int n) -{ - struct csrecord *r; - - if (curmatch == NULL) { - if ((r = TAILQ_FIRST(&csrecords)) == NULL) { - ewprintf("The *cscope* buffer does not exist yet"); - return (FALSE); - } - - } else { - if ((r = TAILQ_NEXT(currecord, entry)) == NULL) { - ewprintf("The end of *cscope* buffer has been reached"); - return (FALSE); - } - } - currecord = r; - curmatch = TAILQ_FIRST(&currecord->matches); - return (jumptomatch()); -} - -/* - * Previous file. - */ -int -csprevfile(int f, int n) -{ - struct csrecord *r; - - if (curmatch == NULL) { - if ((r = TAILQ_FIRST(&csrecords)) == NULL) { - ewprintf("The *cscope* buffer does not exist yet"); - return (FALSE); - } - - } else { - if ((r = TAILQ_PREV(currecord, csrecords, entry)) == NULL) { - ewprintf("The beginning of *cscope* buffer has been" - " reached"); - return (FALSE); - } - } - currecord = r; - curmatch = TAILQ_FIRST(&currecord->matches); - return (jumptomatch()); -} - -/* - * The current symbol location is extracted from currecord->filename and - * curmatch->lineno. Load the file similar to filevisit and goto the - * lineno recorded. - */ -int -jumptomatch(void) -{ - struct buffer *bp; - char *adjf; - - if (curmatch == NULL || currecord == NULL) - return (FALSE); - adjf = adjustname(currecord->filename, TRUE); - if (adjf == NULL) - return (FALSE); - if ((bp = findbuffer(adjf)) == NULL) - return (FALSE); - curbp = bp; - if (showbuffer(bp, curwp, WFFULL) != TRUE) - return (FALSE); - if (bp->b_fname[0] == '\0') { - if (readin(adjf) != TRUE) - killbuffer(bp); - } - gotoline(FFARG, curmatch->lineno); - return (TRUE); - -} - -/* - * Ask for the symbol, construct cscope commandline with the symbol - * and passed in index. Popen cscope, read the output into *cscope* - * buffer and pop it. - */ -int -do_cscope(int i) -{ - struct buffer *bp; - FILE *fpipe; - char pattern[MAX_TOKEN], cmd[BUFSIZ], title[BUFSIZ]; - char *p, *buf; - int clen, nores = 0; - size_t len; - - /* If current buffer isn't a source file just return */ - if (fnmatch("*.[chy]", curbp->b_fname, 0) != 0) { - ewprintf("C-c s not defined"); - return (FALSE); - } - - if (curtoken(0, 1, pattern) == FALSE) - return (FALSE); - p = eread(csprompt[i], pattern, MAX_TOKEN, EFNEW | EFCR | EFDEF); - if (p == NULL) - return (ABORT); - else if (p[0] == '\0') - return (FALSE); - - if (csexists("cscope") == FALSE) { - ewprintf("no such file or directory, cscope"); - return (FALSE); - } - - csflush(); - clen = snprintf(cmd, sizeof(cmd), "cscope -L -%d %s 2>/dev/null", - i, pattern); - if (clen < 0 || clen >= sizeof(cmd)) - return (FALSE); - - if ((fpipe = popen(cmd, "r")) == NULL) { - ewprintf("problem opening pipe"); - return (FALSE); - } - - bp = bfind("*cscope*", TRUE); - if (bclear(bp) != TRUE) - return (FALSE); - bp->b_flag |= BFREADONLY; - - clen = snprintf(title, sizeof(title), "%s%s", csprompt[i], pattern); - if (clen < 0 || clen >= sizeof(title)) - return (FALSE); - addline(bp, title); - addline(bp, ""); - addline(bp, "-------------------------------------------------------------------------------"); - /* All lines are NUL terminated */ - while ((buf = fgetln(fpipe, &len)) != NULL) { - buf[len - 1] = '\0'; - if (addentry(bp, buf) != TRUE) - return (FALSE); - nores = 1; - }; - pclose(fpipe); - addline(bp, "-------------------------------------------------------------------------------"); - if (nores == 0) - ewprintf("No matches were found."); - return (popbuftop(bp, WNONE)); -} - -/* - * For each line read from cscope output, extract the tokens, - * add them to list and pretty print a line in *cscope* buffer. - */ -int -addentry(struct buffer *bp, char *csline) -{ - struct csrecord *r; - struct csmatch *m; - struct cstokens t; - int lineno; - char buf[BUFSIZ]; - const char *errstr; - - r = NULL; - if (getattr(csline, &t) == FALSE) - return (FALSE); - - lineno = strtonum(t.lineno, INT_MIN, INT_MAX, &errstr); - if (errstr) - return (FALSE); - - if (addentryfn == NULL || strcmp(addentryfn, t.fname) != 0) { - if ((r = malloc(sizeof(struct csrecord))) == NULL) - return (FALSE); - addentryr = r; - if ((r->filename = strndup(t.fname, NFILEN)) == NULL) - goto cleanup; - addentryfn = r->filename; - TAILQ_INIT(&r->matches); - if ((m = malloc(sizeof(struct csmatch))) == NULL) - goto cleanup; - m->lineno = lineno; - TAILQ_INSERT_TAIL(&r->matches, m, entry); - TAILQ_INSERT_TAIL(&csrecords, r, entry); - addline(bp, ""); - if (snprintf(buf, sizeof(buf), "*** %s", t.fname) < 0) - goto cleanup; - addline(bp, buf); - } else { - if ((m = malloc(sizeof(struct csmatch))) == NULL) - goto cleanup; - m->lineno = lineno; - TAILQ_INSERT_TAIL(&addentryr->matches, m, entry); - } - prettyprint(bp, &t); - return (TRUE); -cleanup: - free(r); - return (FALSE); -} - -/* - * Cscope line: - */ -int -getattr(char *line, struct cstokens *t) -{ - char *p; - - if ((p = strchr(line, ' ')) == NULL) - return (FALSE); - *p++ = '\0'; - t->fname = line; - line = p; - - if ((p = strchr(line, ' ')) == NULL) - return (FALSE); - *p++ = '\0'; - t->function = line; - line = p; - - if ((p = strchr(line, ' ')) == NULL) - return (FALSE); - *p++ = '\0'; - t->lineno = line; - - if (*p == '\0') - return (FALSE); - t->pattern = p; - - return (TRUE); -} - -void -prettyprint(struct buffer *bp, struct cstokens *t) -{ - char buf[BUFSIZ]; - - if (snprintf(buf, sizeof(buf), "%s[%s]\t\t%s", - t->function, t->lineno, ltrim(t->pattern)) < 0) - return; - addline(bp, buf); -} - -const char * -ltrim(const char *s) -{ - while (isblank(*s)) - s++; - return s; -} - -void -csflush(void) -{ - struct csrecord *r; - struct csmatch *m; - - while ((r = TAILQ_FIRST(&csrecords)) != NULL) { - free(r->filename); - while ((m = TAILQ_FIRST(&r->matches)) != NULL) { - TAILQ_REMOVE(&r->matches, m, entry); - free(m); - } - TAILQ_REMOVE(&csrecords, r, entry); - free(r); - } - addentryr = NULL; - addentryfn = NULL; - currecord = NULL; - curmatch = NULL; -} - -/* - * Check if the cmd exists in $PATH. Split on ":" and iterate through - * all paths in $PATH. - */ -int -csexists(const char *cmd) -{ - char fname[NFILEN], *dir, *path, *pathc, *tmp; - int cmdlen, dlen; - - /* Special case if prog contains '/' */ - if (strchr(cmd, '/')) { - if (access(cmd, F_OK) == -1) - return (FALSE); - else - return (TRUE); - } - if ((tmp = getenv("PATH")) == NULL) - return (FALSE); - if ((pathc = path = strndup(tmp, NFILEN)) == NULL) { - ewprintf("out of memory"); - return (FALSE); - } - cmdlen = strlen(cmd); - while ((dir = strsep(&path, ":")) != NULL) { - if (*dir == '\0') - *dir = '.'; - - dlen = strlen(dir); - while (dir[dlen-1] == '/') - dir[--dlen] = '\0'; /* strip trailing '/' */ - - if (dlen + 1 + cmdlen >= sizeof(fname)) { - ewprintf("path too long"); - goto cleanup; - } - snprintf(fname, sizeof(fname), "%s/%s", dir, cmd); - if(access(fname, F_OK) == 0) { - free(pathc); - return (TRUE); - } - } -cleanup: - free(pathc); - return (FALSE); -} diff --git a/mg/def.h b/mg/def.h deleted file mode 100644 index 1284e94..0000000 --- a/mg/def.h +++ /dev/null @@ -1,707 +0,0 @@ -/* $OpenBSD: def.h,v 1.124 2012/06/14 17:21:22 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * This file is the general header file for all parts - * of the Mg display editor. It contains all of the - * general definitions and macros. It also contains some - * conditional compilation flags. All of the per-system and - * per-terminal definitions are in special header files. - */ - -#include "sysdef.h" /* Order is critical. */ -#include "ttydef.h" -#include "chrdef.h" - -typedef int (*PF)(int, int); /* generally useful type */ - -/* - * Table sizes, etc. - */ -#define NFILEN 1024 /* Length, file name. */ -#define NBUFN NFILEN /* Length, buffer name. */ -#define NLINE 256 /* Length, line. */ -#define PBMODES 4 /* modes per buffer */ -#define NKBDM 256 /* Length, keyboard macro. */ -#define NPAT 80 /* Length, pattern. */ -#define HUGE 1000 /* A rather large number. */ -#define NSRCH 128 /* Undoable search commands. */ -#define NXNAME 64 /* Length, extended command. */ -#define NKNAME 20 /* Length, key names. */ -#define NTIME 50 /* Length, timestamp string. */ -/* - * Universal. - */ -#define FALSE 0 /* False, no, bad, etc. */ -#define TRUE 1 /* True, yes, good, etc. */ -#define ABORT 2 /* Death, ^G, abort, etc. */ - -#define KCLEAR 2 /* clear echo area */ - -/* - * These flag bits keep track of - * some aspects of the last command. The CFCPCN - * flag controls goal column setting. The CFKILL - * flag controls the clearing versus appending - * of data in the kill buffer. - */ -#define CFCPCN 0x0001 /* Last command was C-P, C-N */ -#define CFKILL 0x0002 /* Last command was a kill */ -#define CFINS 0x0004 /* Last command was self-insert */ - -/* - * File I/O. - */ -#define FIOSUC 0 /* Success. */ -#define FIOFNF 1 /* File not found. */ -#define FIOEOF 2 /* End of file. */ -#define FIOERR 3 /* Error. */ -#define FIOLONG 4 /* long line partially read */ -#define FIODIR 5 /* File is a directory */ - -/* - * Directory I/O. - */ -#define DIOSUC 0 /* Success. */ -#define DIOEOF 1 /* End of file. */ -#define DIOERR 2 /* Error. */ - -/* - * Display colors. - */ -#define CNONE 0 /* Unknown color. */ -#define CTEXT 1 /* Text color. */ -#define CMODE 2 /* Mode line color. */ - -/* - * Flags for keyboard invoked functions. - */ -#define FFUNIV 1 /* universal argument */ -#define FFNEGARG 2 /* negative only argument */ -#define FFOTHARG 4 /* other argument */ -#define FFARG 7 /* any argument */ -#define FFRAND 8 /* Called by other function */ - -/* - * Flags for "eread". - */ -#define EFFUNC 0x0001 /* Autocomplete functions. */ -#define EFBUF 0x0002 /* Autocomplete buffers. */ -#define EFFILE 0x0004 /* " files (maybe someday) */ -#define EFAUTO 0x0007 /* Some autocompletion on */ -#define EFNEW 0x0008 /* New prompt. */ -#define EFCR 0x0010 /* Echo CR at end; last read. */ -#define EFDEF 0x0020 /* buffer contains default args */ -#define EFNUL 0x0040 /* Null Minibuffer OK */ - -/* - * Direction of insert into kill ring - */ -#define KNONE 0x00 -#define KFORW 0x01 /* forward insert into kill ring */ -#define KBACK 0x02 /* Backwards insert into kill ring */ -#define KREG 0x04 /* This is a region-based kill */ - -#define MAX_TOKEN 64 - -/* - * This structure holds the starting position - * (as a line/offset pair) and the number of characters in a - * region of a buffer. This makes passing the specification - * of a region around a little bit easier. - */ -struct region { - struct line *r_linep; /* Origin line address. */ - int r_offset; /* Origin line offset. */ - int r_lineno; /* Origin line number */ - RSIZE r_size; /* Length in characters. */ -}; - - -/* - * All text is kept in circularly linked - * lists of "line" structures. These begin at the - * header line (which is the blank line beyond the - * end of the buffer). This line is pointed to by - * the "buffer" structure. Each line contains the number of - * bytes in the line (the "used" size), the size - * of the text array, and the text. The end of line - * is not stored as a byte; it's implied. Future - * additions will include update hints, and a - * list of marks into the line. - */ -struct line { - struct line *l_fp; /* Link to the next line */ - struct line *l_bp; /* Link to the previous line */ - int l_size; /* Allocated size */ - int l_used; /* Used size */ - char *l_text; /* Content of the line */ -}; - -/* - * The rationale behind these macros is that you - * could (with some editing, like changing the type of a line - * link from a "struct line *" to a "REFLINE", and fixing the commands - * like file reading that break the rules) change the actual - * storage representation of lines to use something fancy on - * machines with small address spaces. - */ -#define lforw(lp) ((lp)->l_fp) -#define lback(lp) ((lp)->l_bp) -#define lgetc(lp, n) (CHARMASK((lp)->l_text[(n)])) -#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c)) -#define llength(lp) ((lp)->l_used) -#define ltext(lp) ((lp)->l_text) - -/* - * All repeated structures are kept as linked lists of structures. - * All of these start with a LIST structure (except lines, which - * have their own abstraction). This will allow for - * later conversion to generic list manipulation routines should - * I decide to do that. It does mean that there are four extra - * bytes per window. I feel that this is an acceptable price, - * considering that there are usually only one or two windows. - */ -struct list { - union { - struct mgwin *l_wp; - struct buffer *x_bp; /* l_bp is used by struct line */ - struct list *l_nxt; - } l_p; - char *l_name; -}; - -/* - * Usual hack - to keep from uglifying the code with lotsa - * references through the union, we #define something for it. - */ -#define l_next l_p.l_nxt - -/* - * There is a window structure allocated for - * every active display window. The windows are kept in a - * big list, in top to bottom screen order, with the listhead at - * "wheadp". Each window contains its own values of dot and mark. - * The flag field contains some bits that are set by commands - * to guide redisplay; although this is a bit of a compromise in - * terms of decoupling, the full blown redisplay is just too - * expensive to run for every input character. - */ -struct mgwin { - struct list w_list; /* List header */ - struct buffer *w_bufp; /* Buffer displayed in window */ - struct line *w_linep; /* Top line in the window */ - struct line *w_dotp; /* Line containing "." */ - struct line *w_markp; /* Line containing "mark" */ - int w_doto; /* Byte offset for "." */ - int w_marko; /* Byte offset for "mark" */ - int w_toprow; /* Origin 0 top row of window */ - int w_ntrows; /* # of rows of text in window */ - int w_frame; /* #lines to reframe by. */ - char w_rflag; /* Redisplay Flags. */ - char w_flag; /* Flags. */ - struct line *w_wrapline; - int w_dotline; /* current line number of dot */ - int w_markline; /* current line number of mark */ -}; -#define w_wndp w_list.l_p.l_wp -#define w_name w_list.l_name - -/* - * Window redisplay flags are set by command processors to - * tell the display system what has happened to the buffer - * mapped by the window. Setting "WFFULL" is always a safe thing - * to do, but it may do more work than is necessary. Always try - * to set the simplest action that achieves the required update. - * Because commands set bits in the "w_flag", update will see - * all change flags, and do the most general one. - */ -#define WFFRAME 0x01 /* Force reframe. */ -#define WFMOVE 0x02 /* Movement from line to line. */ -#define WFEDIT 0x04 /* Editing within a line. */ -#define WFFULL 0x08 /* Do a full display. */ -#define WFMODE 0x10 /* Update mode line. */ - -/* - * Window flags - */ -#define WNONE 0x00 /* No special window options. */ -#define WEPHEM 0x01 /* Window is ephemeral. */ - -struct undo_rec; -TAILQ_HEAD(undoq, undo_rec); - -/* - * Text is kept in buffers. A buffer header, described - * below, exists for every buffer in the system. The buffers are - * kept in a big list, so that commands that search for a buffer by - * name can find the buffer header. There is a safe store for the - * dot and mark in the header, but this is only valid if the buffer - * is not being displayed (that is, if "b_nwnd" is 0). The text for - * the buffer is kept in a circularly linked list of lines, with - * a pointer to the header line in "b_headp". - */ -struct buffer { - struct list b_list; /* buffer list pointer */ - struct buffer *b_altb; /* Link to alternate buffer */ - struct line *b_dotp; /* Link to "." line structure */ - struct line *b_markp; /* ditto for mark */ - struct line *b_headp; /* Link to the header line */ - struct maps_s *b_modes[PBMODES]; /* buffer modes */ - int b_doto; /* Offset of "." in above line */ - int b_marko; /* ditto for the "mark" */ - short b_nmodes; /* number of non-fundamental modes */ - char b_nwnd; /* Count of windows on buffer */ - char b_flag; /* Flags */ - char b_fname[NFILEN]; /* File name */ - char b_cwd[NFILEN]; /* working directory */ - struct fileinfo b_fi; /* File attributes */ - struct undoq b_undo; /* Undo actions list */ - int b_undopos; /* Where we were during last undo */ - struct undo_rec *b_undoptr; - int b_dotline; /* Line number of dot */ - int b_markline; /* Line number of mark */ - int b_lines; /* Number of lines in file */ -}; -#define b_bufp b_list.l_p.x_bp -#define b_bname b_list.l_name - -/* Some helper macros, in case they ever change to functions */ -#define bfirstlp(buf) (lforw((buf)->b_headp)) -#define blastlp(buf) (lback((buf)->b_headp)) - -#define BFCHG 0x01 /* Changed. */ -#define BFBAK 0x02 /* Need to make a backup. */ -#ifdef NOTAB -#define BFNOTAB 0x04 /* no tab mode */ -#endif -#define BFOVERWRITE 0x08 /* overwrite mode */ -#define BFREADONLY 0x10 /* read only mode */ -#define BFDIRTY 0x20 /* Buffer was modified elsewhere */ -#define BFIGNDIRTY 0x40 /* Ignore modifications */ -/* - * This structure holds information about recent actions for the Undo command. - */ -struct undo_rec { - TAILQ_ENTRY(undo_rec) next; - enum { - INSERT = 1, - DELETE, - BOUNDARY, - MODIFIED, - DELREG - } type; - struct region region; - int pos; - char *content; -}; - -/* - * Prototypes. - */ - -/* tty.c X */ -void ttinit(void); -void ttreinit(void); -void tttidy(void); -void ttmove(int, int); -void tteeol(void); -void tteeop(void); -void ttbeep(void); -void ttinsl(int, int, int); -void ttdell(int, int, int); -void ttwindow(int, int); -void ttnowindow(void); -void ttcolor(int); -void ttresize(void); - -volatile sig_atomic_t winch_flag; - -/* ttyio.c */ -void ttopen(void); -int ttraw(void); -void ttclose(void); -int ttcooked(void); -int ttputc(int); -void ttflush(void); -int ttgetc(void); -int ttwait(int); -int charswaiting(void); - -/* dir.c */ -void dirinit(void); -int changedir(int, int); -int showcwdir(int, int); -int getcwdir(char *, size_t); - -/* dired.c */ -struct buffer *dired_(char *); - -/* file.c X */ -int fileinsert(int, int); -int filevisit(int, int); -int filevisitalt(int, int); -int filevisitro(int, int); -int poptofile(int, int); -struct buffer *findbuffer(char *); -int readin(char *); -int insertfile(char *, char *, int); -int filewrite(int, int); -int filesave(int, int); -int buffsave(struct buffer *); -int makebkfile(int, int); -int writeout(FILE **, struct buffer *, char *); -void upmodes(struct buffer *); -size_t xbasename(char *, const char *, size_t); - -/* line.c X */ -struct line *lalloc(int); -int lrealloc(struct line *, int); -void lfree(struct line *); -void lchange(int); -int linsert_str(const char *, int); -int linsert(int, int); -int lnewline_at(struct line *, int); -int lnewline(void); -int ldelete(RSIZE, int); -int ldelnewline(void); -int lreplace(RSIZE, char *); -char * linetostr(const struct line *); - -/* yank.c X */ - -void kdelete(void); -int kinsert(int, int); -int kremove(int); -int kchunk(char *, RSIZE, int); -int killline(int, int); -int yank(int, int); - -/* window.c X */ -struct mgwin *new_window(struct buffer *); -void free_window(struct mgwin *); -int reposition(int, int); -int redraw(int, int); -int do_redraw(int, int, int); -int nextwind(int, int); -int prevwind(int, int); -int onlywind(int, int); -int splitwind(int, int); -int enlargewind(int, int); -int shrinkwind(int, int); -int delwind(int, int); - -/* buffer.c */ -int togglereadonly(int, int); -struct buffer *bfind(const char *, int); -int poptobuffer(int, int); -int killbuffer(struct buffer *); -int killbuffer_cmd(int, int); -int savebuffers(int, int); -int listbuffers(int, int); -int addlinef(struct buffer *, char *, ...); -#define addline(bp, text) addlinef(bp, "%s", text) -int anycb(int); -int bclear(struct buffer *); -int showbuffer(struct buffer *, struct mgwin *, int); -int augbname(char *, const char *, size_t); -struct mgwin *popbuf(struct buffer *, int); -int bufferinsert(int, int); -int usebuffer(int, int); -int notmodified(int, int); -int popbuftop(struct buffer *, int); -int getbufcwd(char *, size_t); -int checkdirty(struct buffer *); - -/* display.c */ -int vtresize(int, int, int); -void vtinit(void); -void vttidy(void); -void update(void); -int linenotoggle(int, int); - -/* echo.c X */ -void eerase(void); -int eyorn(const char *); -int eyesno(const char *); -void ewprintf(const char *fmt, ...); -char *ereply(const char *, char *, size_t, ...); -char *eread(const char *, char *, size_t, int, ...); -int getxtra(struct list *, struct list *, int, int); -void free_file_list(struct list *); - -/* fileio.c */ -int ffropen(FILE **, const char *, struct buffer *); -void ffstat(FILE *, struct buffer *); -int ffwopen(FILE **, const char *, struct buffer *); -int ffclose(FILE *, struct buffer *); -int ffputbuf(FILE *, struct buffer *); -int ffgetline(FILE *, char *, int, int *); -int fbackupfile(const char *); -char *adjustname(const char *, int); -char *startupfile(char *); -int copy(char *, char *); -struct list *make_file_list(char *); -int fisdir(const char *); -int fchecktime(struct buffer *); -int fupdstat(struct buffer *); -int backuptohomedir(int, int); -int toggleleavetmp(int, int); - -/* kbd.c X */ -int do_meta(int, int); -int bsmap(int, int); -void ungetkey(int); -int getkey(int); -int doin(void); -int rescan(int, int); -int universal_argument(int, int); -int digit_argument(int, int); -int negative_argument(int, int); -int selfinsert(int, int); -int quote(int, int); - -/* main.c */ -int ctrlg(int, int); -int quit(int, int); - -/* ttyio.c */ -void panic(char *); - -/* cinfo.c */ -char *getkeyname(char *, size_t, int); - -/* basic.c */ -int gotobol(int, int); -int backchar(int, int); -int gotoeol(int, int); -int forwchar(int, int); -int gotobob(int, int); -int gotoeob(int, int); -int forwline(int, int); -int backline(int, int); -void setgoal(void); -int getgoal(struct line *); -int forwpage(int, int); -int backpage(int, int); -int forw1page(int, int); -int back1page(int, int); -int pagenext(int, int); -void isetmark(void); -int setmark(int, int); -int clearmark(int, int); -int swapmark(int, int); -int gotoline(int, int); - -/* random.c X */ -int showcpos(int, int); -int getcolpos(void); -int twiddle(int, int); -int openline(int, int); -int newline(int, int); -int deblank(int, int); -int justone(int, int); -int delwhite(int, int); -int delleadwhite(int, int); -int deltrailwhite(int, int); -int lfindent(int, int); -int indent(int, int); -int forwdel(int, int); -int backdel(int, int); -int space_to_tabstop(int, int); -int backtoindent(int, int); -int joinline(int, int); - -/* tags.c X */ -int findtag(int, int); -int poptag(int, int); -int tagsvisit(int, int); -int curtoken(int, int, char *); - -/* cscope.c */ -int cssymbol(int, int); -int csdefinition(int, int); -int csfuncalled(int, int); -int cscallerfuncs(int, int); -int csfindtext(int, int); -int csegrep(int, int); -int csfindfile(int, int); -int csfindinc(int, int); -int csnextfile(int, int); -int csnextmatch(int, int); -int csprevfile(int, int); -int csprevmatch(int, int); -int cscreatelist(int, int); - -/* extend.c X */ -int insert(int, int); -int bindtokey(int, int); -int localbind(int, int); -int redefine_key(int, int); -int unbindtokey(int, int); -int localunbind(int, int); -int extend(int, int); -int evalexpr(int, int); -int evalbuffer(int, int); -int evalfile(int, int); -int load(const char *); -int excline(char *); - -/* help.c X */ -int desckey(int, int); -int wallchart(int, int); -int help_help(int, int); -int apropos_command(int, int); - -/* paragraph.c X */ -int gotobop(int, int); -int gotoeop(int, int); -int fillpara(int, int); -int killpara(int, int); -int fillword(int, int); -int setfillcol(int, int); - -/* word.c X */ -int backword(int, int); -int forwword(int, int); -int upperword(int, int); -int lowerword(int, int); -int capword(int, int); -int delfword(int, int); -int delbword(int, int); -int inword(void); - -/* region.c X */ -int killregion(int, int); -int copyregion(int, int); -int lowerregion(int, int); -int upperregion(int, int); -int prefixregion(int, int); -int setprefix(int, int); -int region_get_data(struct region *, char *, int); -void region_put_data(const char *, int); -int markbuffer(int, int); -int piperegion(int, int); - -/* search.c X */ -int forwsearch(int, int); -int backsearch(int, int); -int searchagain(int, int); -int forwisearch(int, int); -int backisearch(int, int); -int queryrepl(int, int); -int forwsrch(void); -int backsrch(void); -int readpattern(char *); - -/* spawn.c X */ -int spawncli(int, int); - -/* ttykbd.c X */ -void ttykeymapinit(void); -void ttykeymaptidy(void); - -/* match.c X */ -int showmatch(int, int); - -/* version.c X */ -int showversion(int, int); - -/* macro.c X */ -int definemacro(int, int); -int finishmacro(int, int); -int executemacro(int, int); - -/* modes.c X */ -int indentmode(int, int); -int fillmode(int, int); -int blinkparen(int, int); -#ifdef NOTAB -int notabmode(int, int); -#endif /* NOTAB */ -int overwrite_mode(int, int); -int set_default_mode(int,int); - -#ifdef REGEX -/* re_search.c X */ -int re_forwsearch(int, int); -int re_backsearch(int, int); -int re_searchagain(int, int); -int re_queryrepl(int, int); -int replstr(int, int); -int setcasefold(int, int); -int delmatchlines(int, int); -int delnonmatchlines(int, int); -int cntmatchlines(int, int); -int cntnonmatchlines(int, int); -#endif /* REGEX */ - -/* undo.c X */ -void free_undo_record(struct undo_rec *); -int undo_dump(int, int); -int undo_enabled(void); -int undo_enable(int, int); -int undo_add_boundary(int, int); -void undo_add_modified(void); -int undo_add_insert(struct line *, int, int); -int undo_add_delete(struct line *, int, int, int); -int undo_boundary_enable(int, int); -int undo_add_change(struct line *, int, int); -int undo(int, int); - -/* autoexec.c X */ -int auto_execute(int, int); -PF *find_autoexec(const char *); -int add_autoexec(const char *, const char *); - -/* cmode.c X */ -int cmode(int, int); -int cc_brace(int, int); -int cc_char(int, int); -int cc_tab(int, int); -int cc_indent(int, int); -int cc_lfindent(int, int); - -/* grep.c X */ -int next_error(int, int); -int globalwdtoggle(int, int); -int compile(int, int); - -/* - * Externals. - */ -extern struct buffer *bheadp; -extern struct buffer *curbp; -extern struct mgwin *curwp; -extern struct mgwin *wheadp; -extern int thisflag; -extern int lastflag; -extern int curgoal; -extern int startrow; -extern int epresf; -extern int sgarbf; -extern int mode; -extern int nrow; -extern int ncol; -extern int ttrow; -extern int ttcol; -extern int tttop; -extern int ttbot; -extern int tthue; -extern int defb_nmodes; -extern int defb_flag; -extern char cinfo[]; -extern char *keystrings[]; -extern char pat[NPAT]; -#ifndef NO_DPROMPT -extern char prompt[]; -#endif /* !NO_DPROMPT */ - -/* - * Globals. - */ -int tceeol; -int tcinsl; -int tcdell; -int rptcount; /* successive invocation count */ diff --git a/mg/dir.c b/mg/dir.c deleted file mode 100644 index 2352773..0000000 --- a/mg/dir.c +++ /dev/null @@ -1,77 +0,0 @@ -/* $OpenBSD: dir.c,v 1.19 2008/06/13 20:07:40 kjell Exp $ */ - -/* This file is in the public domain. */ - -/* - * Name: MG 2a - * Directory management functions - * Created: Ron Flax (ron@vsedev.vse.com) - * Modified for MG 2a by Mic Kaczmarczik 03-Aug-1987 - */ - -#include "def.h" - -static char mgcwd[NFILEN]; - -/* - * Initialize anything the directory management routines need. - */ -void -dirinit(void) -{ - mgcwd[0] = '\0'; - if (getcwd(mgcwd, sizeof(mgcwd)) == NULL) { - ewprintf("Can't get current directory!"); - chdir("/"); - } - if (!(mgcwd[0] == '/' && mgcwd [1] == '\0')) - (void)strlcat(mgcwd, "/", sizeof(mgcwd)); -} - -/* - * Change current working directory. - */ -/* ARGSUSED */ -int -changedir(int f, int n) -{ - char bufc[NFILEN], *bufp; - - (void)strlcpy(bufc, mgcwd, sizeof(bufc)); - if ((bufp = eread("Change default directory: ", bufc, NFILEN, - EFDEF | EFNEW | EFCR | EFFILE)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - /* Append trailing slash */ - if (chdir(bufc) == -1) { - ewprintf("Can't change dir to %s", bufc); - return (FALSE); - } - if ((bufp = getcwd(mgcwd, sizeof(mgcwd))) == NULL) - panic("Can't get current directory!"); - if (mgcwd[strlen(mgcwd) - 1] != '/') - (void)strlcat(mgcwd, "/", sizeof(mgcwd)); - ewprintf("Current directory is now %s", bufp); - return (TRUE); -} - -/* - * Show current directory. - */ -/* ARGSUSED */ -int -showcwdir(int f, int n) -{ - ewprintf("Current directory: %s", mgcwd); - return (TRUE); -} - -int -getcwdir(char *buf, size_t len) -{ - if (strlcpy(buf, mgcwd, len) >= len) - return (FALSE); - - return (TRUE); -} diff --git a/mg/dired.c b/mg/dired.c deleted file mode 100644 index 184c9f7..0000000 --- a/mg/dired.c +++ /dev/null @@ -1,779 +0,0 @@ -/* $OpenBSD: dired.c,v 1.51 2012/03/14 13:56:35 lum Exp $ */ - -/* This file is in the public domain. */ - -/* dired module for mg 2a - * by Robert A. Larson - */ - -#include "def.h" -#include "funmap.h" -#include "kbd.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -void dired_init(void); -static int dired(int, int); -static int d_otherwindow(int, int); -static int d_undel(int, int); -static int d_undelbak(int, int); -static int d_findfile(int, int); -static int d_ffotherwindow(int, int); -static int d_expunge(int, int); -static int d_copy(int, int); -static int d_del(int, int); -static int d_rename(int, int); -static int d_exec(int, struct buffer *, const char *, const char *, ...); -static int d_shell_command(int, int); -static int d_create_directory(int, int); -static int d_makename(struct line *, char *, size_t); -static int d_warpdot(struct line *, int *); -static int d_forwpage(int, int); -static int d_backpage(int, int); -static int d_forwline(int, int); -static int d_backline(int, int); -static void reaper(int); - -extern struct keymap_s helpmap, cXmap, metamap; - -static PF dirednul[] = { - setmark, /* ^@ */ - gotobol, /* ^A */ - backchar, /* ^B */ - rescan, /* ^C */ - d_del, /* ^D */ - gotoeol, /* ^E */ - forwchar, /* ^F */ - ctrlg, /* ^G */ - NULL, /* ^H */ -}; - -static PF diredcl[] = { - reposition, /* ^L */ - d_findfile, /* ^M */ - d_forwline, /* ^N */ - rescan, /* ^O */ - d_backline, /* ^P */ - rescan, /* ^Q */ - backisearch, /* ^R */ - forwisearch, /* ^S */ - rescan, /* ^T */ - universal_argument, /* ^U */ - d_forwpage, /* ^V */ - rescan, /* ^W */ - NULL /* ^X */ -}; - -static PF diredcz[] = { - spawncli, /* ^Z */ - NULL, /* esc */ - rescan, /* ^\ */ - rescan, /* ^] */ - rescan, /* ^^ */ - rescan, /* ^_ */ - d_forwline, /* SP */ - d_shell_command, /* ! */ - rescan, /* " */ - rescan, /* # */ - rescan, /* $ */ - rescan, /* % */ - rescan, /* & */ - rescan, /* ' */ - rescan, /* ( */ - rescan, /* ) */ - rescan, /* * */ - d_create_directory /* + */ -}; - -static PF diredc[] = { - d_copy, /* c */ - d_del, /* d */ - d_findfile, /* e */ - d_findfile /* f */ -}; - -static PF diredn[] = { - d_forwline, /* n */ - d_ffotherwindow, /* o */ - d_backline, /* p */ - rescan, /* q */ - d_rename, /* r */ - rescan, /* s */ - rescan, /* t */ - d_undel, /* u */ - rescan, /* v */ - rescan, /* w */ - d_expunge /* x */ -}; - -static PF direddl[] = { - d_undelbak /* del */ -}; - -static PF diredbp[] = { - d_backpage /* v */ -}; - -static PF dirednull[] = { - NULL -}; - -#ifndef DIRED_XMAPS -#define NDIRED_XMAPS 0 /* number of extra map sections */ -#endif /* DIRED_XMAPS */ - -static struct KEYMAPE (1 + IMAPEXT) d_backpagemap = { - 1, - 1 + IMAPEXT, - rescan, - { - { - 'v', 'v', diredbp, NULL - } - } -}; - -static struct KEYMAPE (7 + NDIRED_XMAPS + IMAPEXT) diredmap = { - 7 + NDIRED_XMAPS, - 7 + NDIRED_XMAPS + IMAPEXT, - rescan, - { - { - CCHR('@'), CCHR('H'), dirednul, (KEYMAP *) & helpmap - }, - { - CCHR('L'), CCHR('X'), diredcl, (KEYMAP *) & cXmap - }, - { - CCHR('['), CCHR('['), dirednull, (KEYMAP *) & - d_backpagemap - }, - { - CCHR('Z'), '+', diredcz, (KEYMAP *) & metamap - }, - { - 'c', 'f', diredc, NULL - }, - { - 'n', 'x', diredn, NULL - }, - { - CCHR('?'), CCHR('?'), direddl, NULL - }, -#ifdef DIRED_XMAPS - DIRED_XMAPS, /* map sections for dired mode keys */ -#endif /* DIRED_XMAPS */ - } -}; - -void -dired_init(void) -{ - funmap_add(dired, "dired"); - funmap_add(d_undelbak, "dired-backup-unflag"); - funmap_add(d_copy, "dired-copy-file"); - funmap_add(d_expunge, "dired-do-deletions"); - funmap_add(d_findfile, "dired-find-file"); - funmap_add(d_ffotherwindow, "dired-find-file-other-window"); - funmap_add(d_del, "dired-flag-file-deleted"); - funmap_add(d_forwline, "dired-next-line"); - funmap_add(d_otherwindow, "dired-other-window"); - funmap_add(d_backline, "dired-previous-line"); - funmap_add(d_rename, "dired-rename-file"); - funmap_add(d_backpage, "dired-scroll-down"); - funmap_add(d_forwpage, "dired-scroll-up"); - funmap_add(d_undel, "dired-unflag"); - maps_add((KEYMAP *)&diredmap, "dired"); - dobindkey(fundamental_map, "dired", "^Xd"); -} - -/* ARGSUSED */ -int -dired(int f, int n) -{ - char dname[NFILEN], *bufp, *slash; - struct buffer *bp; - - if (curbp->b_fname && curbp->b_fname[0] != '\0') { - (void)strlcpy(dname, curbp->b_fname, sizeof(dname)); - if ((slash = strrchr(dname, '/')) != NULL) { - *(slash + 1) = '\0'; - } - } else { - if (getcwd(dname, sizeof(dname)) == NULL) - dname[0] = '\0'; - } - - if ((bufp = eread("Dired: ", dname, NFILEN, - EFDEF | EFNEW | EFCR)) == NULL) - return (ABORT); - if (bufp[0] == '\0') - return (FALSE); - if ((bp = dired_(bufp)) == NULL) - return (FALSE); - - curbp = bp; - return (showbuffer(bp, curwp, WFFULL | WFMODE)); -} - -/* ARGSUSED */ -int -d_otherwindow(int f, int n) -{ - char dname[NFILEN], *bufp, *slash; - struct buffer *bp; - struct mgwin *wp; - - if (curbp->b_fname && curbp->b_fname[0] != '\0') { - (void)strlcpy(dname, curbp->b_fname, sizeof(dname)); - if ((slash = strrchr(dname, '/')) != NULL) { - *(slash + 1) = '\0'; - } - } else { - if (getcwd(dname, sizeof(dname)) == NULL) - dname[0] = '\0'; - } - - if ((bufp = eread("Dired other window: ", dname, NFILEN, - EFDEF | EFNEW | EFCR)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - if ((bp = dired_(bufp)) == NULL) - return (FALSE); - if ((wp = popbuf(bp, WNONE)) == NULL) - return (FALSE); - curbp = bp; - curwp = wp; - return (TRUE); -} - -/* ARGSUSED */ -int -d_del(int f, int n) -{ - if (n < 0) - return (FALSE); - while (n--) { - if (llength(curwp->w_dotp) > 0) - lputc(curwp->w_dotp, 0, 'D'); - if (lforw(curwp->w_dotp) != curbp->b_headp) - curwp->w_dotp = lforw(curwp->w_dotp); - } - curwp->w_rflag |= WFEDIT | WFMOVE; - curwp->w_doto = 0; - return (TRUE); -} - -/* ARGSUSED */ -int -d_undel(int f, int n) -{ - if (n < 0) - return (d_undelbak(f, -n)); - while (n--) { - if (llength(curwp->w_dotp) > 0) - lputc(curwp->w_dotp, 0, ' '); - if (lforw(curwp->w_dotp) != curbp->b_headp) - curwp->w_dotp = lforw(curwp->w_dotp); - } - curwp->w_rflag |= WFEDIT | WFMOVE; - curwp->w_doto = 0; - return (TRUE); -} - -/* ARGSUSED */ -int -d_undelbak(int f, int n) -{ - if (n < 0) - return (d_undel(f, -n)); - while (n--) { - if (llength(curwp->w_dotp) > 0) - lputc(curwp->w_dotp, 0, ' '); - if (lback(curwp->w_dotp) != curbp->b_headp) - curwp->w_dotp = lback(curwp->w_dotp); - } - curwp->w_doto = 0; - curwp->w_rflag |= WFEDIT | WFMOVE; - return (TRUE); -} - -/* ARGSUSED */ -int -d_findfile(int f, int n) -{ - struct buffer *bp; - int s; - char fname[NFILEN]; - - if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT) - return (FALSE); - if (s == TRUE) - bp = dired_(fname); - else - bp = findbuffer(fname); - if (bp == NULL) - return (FALSE); - curbp = bp; - if (showbuffer(bp, curwp, WFFULL) != TRUE) - return (FALSE); - if (bp->b_fname[0] != 0) - return (TRUE); - return (readin(fname)); -} - -/* ARGSUSED */ -int -d_ffotherwindow(int f, int n) -{ - char fname[NFILEN]; - int s; - struct buffer *bp; - struct mgwin *wp; - - if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT) - return (FALSE); - if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL) - return (FALSE); - if ((wp = popbuf(bp, WNONE)) == NULL) - return (FALSE); - curbp = bp; - curwp = wp; - if (bp->b_fname[0] != 0) - return (TRUE); /* never true for dired buffers */ - return (readin(fname)); -} - -/* ARGSUSED */ -int -d_expunge(int f, int n) -{ - struct line *lp, *nlp; - char fname[NFILEN], sname[NFILEN]; - - for (lp = bfirstlp(curbp); lp != curbp->b_headp; lp = nlp) { - nlp = lforw(lp); - if (llength(lp) && lgetc(lp, 0) == 'D') { - switch (d_makename(lp, fname, sizeof(fname))) { - case ABORT: - ewprintf("Bad line in dired buffer"); - return (FALSE); - case FALSE: - if (unlink(fname) < 0) { - (void)xbasename(sname, fname, NFILEN); - ewprintf("Could not delete '%s'", sname); - return (FALSE); - } - break; - case TRUE: - if (rmdir(fname) < 0) { - (void)xbasename(sname, fname, NFILEN); - ewprintf("Could not delete directory " - "'%s'", sname); - return (FALSE); - } - break; - } - lfree(lp); - curwp->w_bufp->b_lines--; - curwp->w_rflag |= WFFULL; - } - } - return (TRUE); -} - -/* ARGSUSED */ -int -d_copy(int f, int n) -{ - char frname[NFILEN], toname[NFILEN], sname[NFILEN], *bufp; - int ret; - size_t off; - struct buffer *bp; - - if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE) { - ewprintf("Not a file"); - return (FALSE); - } - off = strlcpy(toname, curbp->b_fname, sizeof(toname)); - if (off >= sizeof(toname) - 1) { /* can't happen, really */ - ewprintf("Directory name too long"); - return (FALSE); - } - (void)xbasename(sname, frname, NFILEN); - bufp = eread("Copy %s to: ", toname, sizeof(toname), - EFDEF | EFNEW | EFCR, sname); - if (bufp == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - ret = (copy(frname, toname) >= 0) ? TRUE : FALSE; - if (ret != TRUE) - return (ret); - bp = dired_(curbp->b_fname); - return (showbuffer(bp, curwp, WFFULL | WFMODE)); -} - -/* ARGSUSED */ -int -d_rename(int f, int n) -{ - char frname[NFILEN], toname[NFILEN], *bufp; - int ret; - size_t off; - struct buffer *bp; - char sname[NFILEN]; - - if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE) { - ewprintf("Not a file"); - return (FALSE); - } - off = strlcpy(toname, curbp->b_fname, sizeof(toname)); - if (off >= sizeof(toname) - 1) { /* can't happen, really */ - ewprintf("Directory name too long"); - return (FALSE); - } - (void)xbasename(sname, frname, NFILEN); - bufp = eread("Rename %s to: ", toname, - sizeof(toname), EFDEF | EFNEW | EFCR, sname); - if (bufp == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - ret = (rename(frname, toname) >= 0) ? TRUE : FALSE; - if (ret != TRUE) - return (ret); - bp = dired_(curbp->b_fname); - return (showbuffer(bp, curwp, WFFULL | WFMODE)); -} - -/* ARGSUSED */ -void -reaper(int signo __attribute__((unused))) -{ - int save_errno = errno, status; - - while (waitpid(-1, &status, WNOHANG) >= 0) - ; - errno = save_errno; -} - -/* - * Pipe the currently selected file through a shell command. - */ -/* ARGSUSED */ -int -d_shell_command(int f, int n) -{ - char command[512], fname[MAXPATHLEN], *bufp; - struct buffer *bp; - struct mgwin *wp; - char sname[NFILEN]; - - bp = bfind("*Shell Command Output*", TRUE); - if (bclear(bp) != TRUE) - return (ABORT); - - if (d_makename(curwp->w_dotp, fname, sizeof(fname)) != FALSE) { - ewprintf("bad line"); - return (ABORT); - } - - command[0] = '\0'; - (void)xbasename(sname, fname, NFILEN); - bufp = eread("! on %s: ", command, sizeof(command), EFNEW, sname); - if (bufp == NULL) - return (ABORT); - - if (d_exec(0, bp, fname, "sh", "-c", command, NULL) != TRUE) - return (ABORT); - - if ((wp = popbuf(bp, WNONE)) == NULL) - return (ABORT); /* XXX - free the buffer?? */ - curwp = wp; - curbp = wp->w_bufp; - return (TRUE); -} - -/* - * Pipe input file to cmd and insert the command's output in the - * given buffer. Each line will be prefixed with the given - * number of spaces. - */ -static int -d_exec(int space, struct buffer *bp, const char *input, const char *cmd, ...) -{ - char buf[BUFSIZ]; - va_list ap; - struct sigaction olda, newa; - char **argv = NULL, *cp; - FILE *fin; - int fds[2] = { -1, -1 }; - int infd = -1; - int ret = (ABORT), n; - pid_t pid; - - if (sigaction(SIGCHLD, NULL, &olda) == -1) - return (ABORT); - - /* Find the number of arguments. */ - va_start(ap, cmd); - for (n = 2; va_arg(ap, char *) != NULL; n++) - ; - va_end(ap); - - /* Allocate and build the argv. */ - if ((argv = calloc(n, sizeof(*argv))) == NULL) { - ewprintf("Can't allocate argv : %s", strerror(errno)); - goto out; - } - - n = 1; - argv[0] = (char *)cmd; - va_start(ap, cmd); - while ((argv[n] = va_arg(ap, char *)) != NULL) - n++; - va_end(ap); - - if (input == NULL) - input = "/dev/null"; - - if ((infd = open(input, O_RDONLY)) == -1) { - ewprintf("Can't open input file : %s", strerror(errno)); - goto out; - } - - if (pipe(fds) == -1) { - ewprintf("Can't create pipe : %s", strerror(errno)); - goto out; - } - - newa.sa_handler = reaper; - newa.sa_flags = 0; - if (sigaction(SIGCHLD, &newa, NULL) == -1) - goto out; - - if ((pid = fork()) == -1) { - ewprintf("Can't fork"); - goto out; - } - - switch (pid) { - case 0: /* Child */ - close(fds[0]); - dup2(infd, STDIN_FILENO); - dup2(fds[1], STDOUT_FILENO); - dup2(fds[1], STDERR_FILENO); - if (execvp(argv[0], argv) == -1) - ewprintf("Can't exec %s: %s", argv[0], strerror(errno)); - exit(1); - break; - default: /* Parent */ - close(infd); - close(fds[1]); - infd = fds[1] = -1; - if ((fin = fdopen(fds[0], "r")) == NULL) - goto out; - while (fgets(buf, sizeof(buf), fin) != NULL) { - cp = strrchr(buf, '\n'); - if (cp == NULL && !feof(fin)) { /* too long a line */ - int c; - addlinef(bp, "%*s%s...", space, "", buf); - while ((c = getc(fin)) != EOF && c != '\n') - ; - continue; - } else if (cp) - *cp = '\0'; - addlinef(bp, "%*s%s", space, "", buf); - } - fclose(fin); - break; - } - ret = (TRUE); - -out: - if (sigaction(SIGCHLD, &olda, NULL) == -1) - ewprintf("Warning, couldn't reset previous signal handler"); - if (fds[0] != -1) - close(fds[0]); - if (fds[1] != -1) - close(fds[1]); - if (infd != -1) - close(infd); - if (argv != NULL) - free(argv); - return ret; -} - -/* ARGSUSED */ -int -d_create_directory(int f, int n) -{ - char tocreate[MAXPATHLEN], *bufp; - size_t off; - struct buffer *bp; - - off = strlcpy(tocreate, curbp->b_fname, sizeof(tocreate)); - if (off >= sizeof(tocreate) - 1) - return (FALSE); - if ((bufp = eread("Create directory: ", tocreate, - sizeof(tocreate), EFDEF | EFNEW | EFCR)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - if (mkdir(tocreate, 0755) == -1) { - ewprintf("Creating directory: %s, %s", strerror(errno), - tocreate); - return (FALSE); - } - bp = dired_(curbp->b_fname); - return (showbuffer(bp, curwp, WFFULL | WFMODE)); -} - -static int -d_makename(struct line *lp, char *fn, size_t len) -{ - int start, nlen; - char *namep; - - if (d_warpdot(lp, &start) == FALSE) - return (ABORT); - namep = &lp->l_text[start]; - nlen = llength(lp) - start; - - if (snprintf(fn, len, "%s%.*s", curbp->b_fname, nlen, namep) >= len) - return (ABORT); /* Name is too long. */ - - /* Return TRUE if the entry is a directory. */ - return ((lgetc(lp, 2) == 'd') ? TRUE : FALSE); -} - -#define NAME_FIELD 9 - -static int -d_warpdot(struct line *dotp, int *doto) -{ - char *tp = dotp->l_text; - int off = 0, field = 0, len; - - /* - * Find the byte offset to the (space-delimited) filename - * field in formatted ls output. - */ - len = llength(dotp); - while (off < len) { - if (tp[off++] == ' ') { - if (++field == NAME_FIELD) { - *doto = off; - return (TRUE); - } - /* Skip the space. */ - while (off < len && tp[off] == ' ') - off++; - } - } - /* We didn't find the field. */ - *doto = 0; - return (FALSE); -} - -static int -d_forwpage(int f, int n) -{ - forwpage(f | FFRAND, n); - return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); -} - -static int -d_backpage (int f, int n) -{ - backpage(f | FFRAND, n); - return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); -} - -static int -d_forwline (int f, int n) -{ - forwline(f | FFRAND, n); - return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); -} - -static int -d_backline (int f, int n) -{ - backline(f | FFRAND, n); - return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); -} - -/* - * XXX dname needs to have enough place to store an additional '/'. - */ -struct buffer * -dired_(char *dname) -{ - struct buffer *bp; - int len, i; - - if ((fopen(dname,"r")) == NULL) { - if (errno == EACCES) - ewprintf("Permission denied"); - return (NULL); - } - if ((dname = adjustname(dname, FALSE)) == NULL) { - ewprintf("Bad directory name"); - return (NULL); - } - /* this should not be done, instead adjustname() should get a flag */ - len = strlen(dname); - if (dname[len - 1] != '/') { - dname[len++] = '/'; - dname[len] = '\0'; - } - if ((bp = findbuffer(dname)) == NULL) { - ewprintf("Could not create buffer"); - return (NULL); - } - if (bclear(bp) != TRUE) - return (NULL); - bp->b_flag |= BFREADONLY; - - if ((d_exec(2, bp, NULL, "ls", "-al", dname, NULL)) != TRUE) - return (NULL); - - /* Find the line with ".." on it. */ - bp->b_dotp = bfirstlp(bp); - for (i = 0; i < bp->b_lines; i++) { - bp->b_dotp = lforw(bp->b_dotp); - if (d_warpdot(bp->b_dotp, &bp->b_doto) == FALSE) - continue; - if (strcmp(ltext(bp->b_dotp) + bp->b_doto, "..") == 0) - break; - } - - /* We want dot on the entry right after "..", if possible. */ - if (++i < bp->b_lines - 2) - bp->b_dotp = lforw(bp->b_dotp); - d_warpdot(bp->b_dotp, &bp->b_doto); - - (void)strlcpy(bp->b_fname, dname, sizeof(bp->b_fname)); - (void)strlcpy(bp->b_cwd, dname, sizeof(bp->b_cwd)); - if ((bp->b_modes[1] = name_mode("dired")) == NULL) { - bp->b_modes[0] = name_mode("fundamental"); - ewprintf("Could not find mode dired"); - return (NULL); - } - bp->b_nmodes = 1; - return (bp); -} diff --git a/mg/display.c b/mg/display.c deleted file mode 100644 index ba7c580..0000000 --- a/mg/display.c +++ /dev/null @@ -1,1064 +0,0 @@ -/* $OpenBSD: display.c,v 1.37 2009/06/04 02:23:37 kjell Exp $ */ - -/* This file is in the public domain. */ - -/* - * The functions in this file handle redisplay. The - * redisplay system knows almost nothing about the editing - * process; the editing functions do, however, set some - * hints to eliminate a lot of the grinding. There is more - * that can be done; the "vtputc" interface is a real - * pig. - */ -#include "def.h" -#include "kbd.h" - -#include - -/* - * You can change these back to the types - * implied by the name if you get tight for space. If you - * make both of them "int" you get better code on the VAX. - * They do nothing if this is not Gosling redisplay, except - * for change the size of a structure that isn't used. - * A bit of a cheat. - */ -#define XCHAR int -#define XSHORT int - -#ifdef STANDOUT_GLITCH -#include -#endif - -/* - * A video structure always holds - * an array of characters whose length is equal to - * the longest line possible. v_text is allocated - * dynamically to fit the screen width. - */ -struct video { - short v_hash; /* Hash code, for compares. */ - short v_flag; /* Flag word. */ - short v_color; /* Color of the line. */ - XSHORT v_cost; /* Cost of display. */ - char *v_text; /* The actual characters. */ -}; - -#define VFCHG 0x0001 /* Changed. */ -#define VFHBAD 0x0002 /* Hash and cost are bad. */ -#define VFEXT 0x0004 /* extended line (beond ncol) */ - -/* - * SCORE structures hold the optimal - * trace trajectory, and the cost of redisplay, when - * the dynamic programming redisplay code is used. - * If no fancy redisplay, this isn't used. The trace index - * fields can be "char", and the cost a "short", but - * this makes the code worse on the VAX. - */ -struct score { - XCHAR s_itrace; /* "i" index for track back. */ - XCHAR s_jtrace; /* "j" index for trace back. */ - XSHORT s_cost; /* Display cost. */ -}; - -void vtmove(int, int); -void vtputc(int); -void vtpute(int); -int vtputs(const char *); -void vteeol(void); -void updext(int, int); -void modeline(struct mgwin *); -void setscores(int, int); -void traceback(int, int, int, int); -void ucopy(struct video *, struct video *); -void uline(int, struct video *, struct video *); -void hash(struct video *); - - -int sgarbf = TRUE; /* TRUE if screen is garbage. */ -int vtrow = HUGE; /* Virtual cursor row. */ -int vtcol = HUGE; /* Virtual cursor column. */ -int tthue = CNONE; /* Current color. */ -int ttrow = HUGE; /* Physical cursor row. */ -int ttcol = HUGE; /* Physical cursor column. */ -int tttop = HUGE; /* Top of scroll region. */ -int ttbot = HUGE; /* Bottom of scroll region. */ -int lbound = 0; /* leftmost bound of the current */ - /* line being displayed */ - -struct video **vscreen; /* Edge vector, virtual. */ -struct video **pscreen; /* Edge vector, physical. */ -struct video *video; /* Actual screen data. */ -struct video blanks; /* Blank line image. */ - -/* - * This matrix is written as an array because - * we do funny things in the "setscores" routine, which - * is very compute intensive, to make the subscripts go away. - * It would be "SCORE score[NROW][NROW]" in old speak. - * Look at "setscores" to understand what is up. - */ -struct score *score; /* [NROW * NROW] */ - -#ifndef LINENOMODE -#define LINENOMODE TRUE -#endif /* !LINENOMODE */ -static int linenos = LINENOMODE; - -/* Is macro recording enabled? */ -extern int macrodef; -/* Is working directory global? */ -extern int globalwd; - -/* - * Since we don't have variables (we probably should) these are command - * processors for changing the values of mode flags. - */ -/* ARGSUSED */ -int -linenotoggle(int f, int n) -{ - if (f & FFARG) - linenos = n > 0; - else - linenos = !linenos; - - sgarbf = TRUE; - - return (TRUE); -} - -/* - * Reinit the display data structures, this is called when the terminal - * size changes. - */ -int -vtresize(int force, int newrow, int newcol) -{ - int i; - int rowchanged, colchanged; - static int first_run = 1; - struct video *vp; - - if (newrow < 1 || newcol < 1) - return (FALSE); - - rowchanged = (newrow != nrow); - colchanged = (newcol != ncol); - -#define TRYREALLOC(a, n) do { \ - void *tmp; \ - if ((tmp = realloc((a), (n))) == NULL) { \ - panic("out of memory in display code"); \ - } \ - (a) = tmp; \ - } while (0) - - /* No update needed */ - if (!first_run && !force && !rowchanged && !colchanged) - return (TRUE); - - if (first_run) - memset(&blanks, 0, sizeof(blanks)); - - if (rowchanged || first_run) { - int vidstart; - - /* - * This is not pretty. - */ - if (nrow == 0) - vidstart = 0; - else - vidstart = 2 * (nrow - 1); - - /* - * We're shrinking, free some internal data. - */ - if (newrow < nrow) { - for (i = 2 * (newrow - 1); i < 2 * (nrow - 1); i++) { - free(video[i].v_text); - video[i].v_text = NULL; - } - } - - TRYREALLOC(score, newrow * newrow * sizeof(struct score)); - TRYREALLOC(vscreen, (newrow - 1) * sizeof(struct video *)); - TRYREALLOC(pscreen, (newrow - 1) * sizeof(struct video *)); - TRYREALLOC(video, (2 * (newrow - 1)) * sizeof(struct video)); - - /* - * Zero-out the entries we just allocated. - */ - for (i = vidstart; i < 2 * (newrow - 1); i++) - memset(&video[i], 0, sizeof(struct video)); - - /* - * Reinitialize vscreen and pscreen arrays completely. - */ - vp = &video[0]; - for (i = 0; i < newrow - 1; ++i) { - vscreen[i] = vp; - ++vp; - pscreen[i] = vp; - ++vp; - } - } - if (rowchanged || colchanged || first_run) { - for (i = 0; i < 2 * (newrow - 1); i++) - TRYREALLOC(video[i].v_text, newcol * sizeof(char)); - TRYREALLOC(blanks.v_text, newcol * sizeof(char)); - } - - nrow = newrow; - ncol = newcol; - - if (ttrow > nrow) - ttrow = nrow; - if (ttcol > ncol) - ttcol = ncol; - - first_run = 0; - return (TRUE); -} - -#undef TRYREALLOC - -/* - * Initialize the data structures used - * by the display code. The edge vectors used - * to access the screens are set up. The operating - * system's terminal I/O channel is set up. Fill the - * "blanks" array with ASCII blanks. The rest is done - * at compile time. The original window is marked - * as needing full update, and the physical screen - * is marked as garbage, so all the right stuff happens - * on the first call to redisplay. - */ -void -vtinit(void) -{ - int i; - - ttopen(); - ttinit(); - - /* - * ttinit called ttresize(), which called vtresize(), so our data - * structures are setup correctly. - */ - - blanks.v_color = CTEXT; - for (i = 0; i < ncol; ++i) - blanks.v_text[i] = ' '; -} - -/* - * Tidy up the virtual display system - * in anticipation of a return back to the host - * operating system. Right now all we do is position - * the cursor to the last line, erase the line, and - * close the terminal channel. - */ -void -vttidy(void) -{ - ttcolor(CTEXT); - ttnowindow(); /* No scroll window. */ - ttmove(nrow - 1, 0); /* Echo line. */ - tteeol(); - tttidy(); - ttflush(); - ttclose(); -} - -/* - * Move the virtual cursor to an origin - * 0 spot on the virtual display screen. I could - * store the column as a character pointer to the spot - * on the line, which would make "vtputc" a little bit - * more efficient. No checking for errors. - */ -void -vtmove(int row, int col) -{ - vtrow = row; - vtcol = col; -} - -/* - * Write a character to the virtual display, - * dealing with long lines and the display of unprintable - * things like control characters. Also expand tabs every 8 - * columns. This code only puts printing characters into - * the virtual display image. Special care must be taken when - * expanding tabs. On a screen whose width is not a multiple - * of 8, it is possible for the virtual cursor to hit the - * right margin before the next tab stop is reached. This - * makes the tab code loop if you are not careful. - * Three guesses how we found this. - */ -void -vtputc(int c) -{ - struct video *vp; - - c &= 0xff; - - vp = vscreen[vtrow]; - if (vtcol >= ncol) - vp->v_text[ncol - 1] = '$'; - else if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif - ) { - do { - vtputc(' '); - } while (vtcol < ncol && (vtcol & 0x07) != 0); - } else if (ISCTRL(c)) { - vtputc('^'); - vtputc(CCHR(c)); - } else if (isprint(c)) - vp->v_text[vtcol++] = c; - else { - char bf[5]; - - snprintf(bf, sizeof(bf), "\\%o", c); - vtputs(bf); - } -} - -/* - * Put a character to the virtual screen in an extended line. If we are not - * yet on left edge, don't print it yet. Check for overflow on the right - * margin. - */ -void -vtpute(int c) -{ - struct video *vp; - - c &= 0xff; - - vp = vscreen[vtrow]; - if (vtcol >= ncol) - vp->v_text[ncol - 1] = '$'; - else if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif - ) { - do { - vtpute(' '); - } while (((vtcol + lbound) & 0x07) != 0 && vtcol < ncol); - } else if (ISCTRL(c) != FALSE) { - vtpute('^'); - vtpute(CCHR(c)); - } else { - if (vtcol >= 0) - vp->v_text[vtcol] = c; - ++vtcol; - } -} - -/* - * Erase from the end of the software cursor to the end of the line on which - * the software cursor is located. The display routines will decide if a - * hardware erase to end of line command should be used to display this. - */ -void -vteeol(void) -{ - struct video *vp; - - vp = vscreen[vtrow]; - while (vtcol < ncol) - vp->v_text[vtcol++] = ' '; -} - -/* - * Make sure that the display is - * right. This is a three part process. First, - * scan through all of the windows looking for dirty - * ones. Check the framing, and refresh the screen. - * Second, make sure that "currow" and "curcol" are - * correct for the current window. Third, make the - * virtual and physical screens the same. - */ -void -update(void) -{ - struct line *lp; - struct mgwin *wp; - struct video *vp1; - struct video *vp2; - int c, i, j; - int hflag; - int currow, curcol; - int offs, size; - - if (charswaiting()) - return; - if (sgarbf) { /* must update everything */ - wp = wheadp; - while (wp != NULL) { - wp->w_rflag |= WFMODE | WFFULL; - wp = wp->w_wndp; - } - } - if (linenos) { - wp = wheadp; - while (wp != NULL) { - wp->w_rflag |= WFMODE; - wp = wp->w_wndp; - } - } - hflag = FALSE; /* Not hard. */ - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - /* - * Nothing to be done. - */ - if (wp->w_rflag == 0) - continue; - - if ((wp->w_rflag & WFFRAME) == 0) { - lp = wp->w_linep; - for (i = 0; i < wp->w_ntrows; ++i) { - if (lp == wp->w_dotp) - goto out; - if (lp == wp->w_bufp->b_headp) - break; - lp = lforw(lp); - } - } - /* - * Put the middle-line in place. - */ - i = wp->w_frame; - if (i > 0) { - --i; - if (i >= wp->w_ntrows) - i = wp->w_ntrows - 1; - } else if (i < 0) { - i += wp->w_ntrows; - if (i < 0) - i = 0; - } else - i = wp->w_ntrows / 2; /* current center, no change */ - - /* - * Find the line. - */ - lp = wp->w_dotp; - while (i != 0 && lback(lp) != wp->w_bufp->b_headp) { - --i; - lp = lback(lp); - } - wp->w_linep = lp; - wp->w_rflag |= WFFULL; /* Force full. */ - out: - lp = wp->w_linep; /* Try reduced update. */ - i = wp->w_toprow; - if ((wp->w_rflag & ~WFMODE) == WFEDIT) { - while (lp != wp->w_dotp) { - ++i; - lp = lforw(lp); - } - vscreen[i]->v_color = CTEXT; - vscreen[i]->v_flag |= (VFCHG | VFHBAD); - vtmove(i, 0); - for (j = 0; j < llength(lp); ++j) - vtputc(lgetc(lp, j)); - vteeol(); - } else if ((wp->w_rflag & (WFEDIT | WFFULL)) != 0) { - hflag = TRUE; - while (i < wp->w_toprow + wp->w_ntrows) { - vscreen[i]->v_color = CTEXT; - vscreen[i]->v_flag |= (VFCHG | VFHBAD); - vtmove(i, 0); - if (lp != wp->w_bufp->b_headp) { - for (j = 0; j < llength(lp); ++j) - vtputc(lgetc(lp, j)); - lp = lforw(lp); - } - vteeol(); - ++i; - } - } - if ((wp->w_rflag & WFMODE) != 0) - modeline(wp); - wp->w_rflag = 0; - wp->w_frame = 0; - } - lp = curwp->w_linep; /* Cursor location. */ - currow = curwp->w_toprow; - while (lp != curwp->w_dotp) { - ++currow; - lp = lforw(lp); - } - curcol = 0; - i = 0; - while (i < curwp->w_doto) { - c = lgetc(lp, i++); - if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif - ) { - curcol |= 0x07; - curcol++; - } else if (ISCTRL(c) != FALSE) - curcol += 2; - else if (isprint(c)) - curcol++; - else { - char bf[5]; - - snprintf(bf, sizeof(bf), "\\%o", c); - curcol += strlen(bf); - } - } - if (curcol >= ncol - 1) { /* extended line. */ - /* flag we are extended and changed */ - vscreen[currow]->v_flag |= VFEXT | VFCHG; - updext(currow, curcol); /* and output extended line */ - } else - lbound = 0; /* not extended line */ - - /* - * Make sure no lines need to be de-extended because the cursor is no - * longer on them. - */ - wp = wheadp; - while (wp != NULL) { - lp = wp->w_linep; - i = wp->w_toprow; - while (i < wp->w_toprow + wp->w_ntrows) { - if (vscreen[i]->v_flag & VFEXT) { - /* always flag extended lines as changed */ - vscreen[i]->v_flag |= VFCHG; - if ((wp != curwp) || (lp != wp->w_dotp) || - (curcol < ncol - 1)) { - vtmove(i, 0); - for (j = 0; j < llength(lp); ++j) - vtputc(lgetc(lp, j)); - vteeol(); - /* this line no longer is extended */ - vscreen[i]->v_flag &= ~VFEXT; - } - } - lp = lforw(lp); - ++i; - } - /* if garbaged then fix up mode lines */ - if (sgarbf != FALSE) - vscreen[i]->v_flag |= VFCHG; - /* and onward to the next window */ - wp = wp->w_wndp; - } - - if (sgarbf != FALSE) { /* Screen is garbage. */ - sgarbf = FALSE; /* Erase-page clears. */ - epresf = FALSE; /* The message area. */ - tttop = HUGE; /* Forget where you set. */ - ttbot = HUGE; /* scroll region. */ - tthue = CNONE; /* Color unknown. */ - ttmove(0, 0); - tteeop(); - for (i = 0; i < nrow - 1; ++i) { - uline(i, vscreen[i], &blanks); - ucopy(vscreen[i], pscreen[i]); - } - ttmove(currow, curcol - lbound); - ttflush(); - return; - } - if (hflag != FALSE) { /* Hard update? */ - for (i = 0; i < nrow - 1; ++i) {/* Compute hash data. */ - hash(vscreen[i]); - hash(pscreen[i]); - } - offs = 0; /* Get top match. */ - while (offs != nrow - 1) { - vp1 = vscreen[offs]; - vp2 = pscreen[offs]; - if (vp1->v_color != vp2->v_color - || vp1->v_hash != vp2->v_hash) - break; - uline(offs, vp1, vp2); - ucopy(vp1, vp2); - ++offs; - } - if (offs == nrow - 1) { /* Might get it all. */ - ttmove(currow, curcol - lbound); - ttflush(); - return; - } - size = nrow - 1; /* Get bottom match. */ - while (size != offs) { - vp1 = vscreen[size - 1]; - vp2 = pscreen[size - 1]; - if (vp1->v_color != vp2->v_color - || vp1->v_hash != vp2->v_hash) - break; - uline(size - 1, vp1, vp2); - ucopy(vp1, vp2); - --size; - } - if ((size -= offs) == 0) /* Get screen size. */ - panic("Illegal screen size in update"); - setscores(offs, size); /* Do hard update. */ - traceback(offs, size, size, size); - for (i = 0; i < size; ++i) - ucopy(vscreen[offs + i], pscreen[offs + i]); - ttmove(currow, curcol - lbound); - ttflush(); - return; - } - for (i = 0; i < nrow - 1; ++i) { /* Easy update. */ - vp1 = vscreen[i]; - vp2 = pscreen[i]; - if ((vp1->v_flag & VFCHG) != 0) { - uline(i, vp1, vp2); - ucopy(vp1, vp2); - } - } - ttmove(currow, curcol - lbound); - ttflush(); -} - -/* - * Update a saved copy of a line, - * kept in a video structure. The "vvp" is - * the one in the "vscreen". The "pvp" is the one - * in the "pscreen". This is called to make the - * virtual and physical screens the same when - * display has done an update. - */ -void -ucopy(struct video *vvp, struct video *pvp) -{ - vvp->v_flag &= ~VFCHG; /* Changes done. */ - pvp->v_flag = vvp->v_flag; /* Update model. */ - pvp->v_hash = vvp->v_hash; - pvp->v_cost = vvp->v_cost; - pvp->v_color = vvp->v_color; - bcopy(vvp->v_text, pvp->v_text, ncol); -} - -/* - * updext: update the extended line which the cursor is currently on at a - * column greater than the terminal width. The line will be scrolled right or - * left to let the user see where the cursor is. - */ -void -updext(int currow, int curcol) -{ - struct line *lp; /* pointer to current line */ - int j; /* index into line */ - - if (ncol < 2) - return; - - /* - * calculate what column the left bound should be - * (force cursor into middle half of screen) - */ - lbound = curcol - (curcol % (ncol >> 1)) - (ncol >> 2); - - /* - * scan through the line outputing characters to the virtual screen - * once we reach the left edge - */ - vtmove(currow, -lbound); /* start scanning offscreen */ - lp = curwp->w_dotp; /* line to output */ - for (j = 0; j < llength(lp); ++j) /* until the end-of-line */ - vtpute(lgetc(lp, j)); - vteeol(); /* truncate the virtual line */ - vscreen[currow]->v_text[0] = '$'; /* and put a '$' in column 1 */ -} - -/* - * Update a single line. This routine only - * uses basic functionality (no insert and delete character, - * but erase to end of line). The "vvp" points at the video - * structure for the line on the virtual screen, and the "pvp" - * is the same for the physical screen. Avoid erase to end of - * line when updating CMODE color lines, because of the way that - * reverse video works on most terminals. - */ -void -uline(int row, struct video *vvp, struct video *pvp) -{ - char *cp1; - char *cp2; - char *cp3; - char *cp4; - char *cp5; - int nbflag; - - if (vvp->v_color != pvp->v_color) { /* Wrong color, do a */ - ttmove(row, 0); /* full redraw. */ -#ifdef STANDOUT_GLITCH - if (pvp->v_color != CTEXT && magic_cookie_glitch >= 0) - tteeol(); -#endif - ttcolor(vvp->v_color); -#ifdef STANDOUT_GLITCH - cp1 = &vvp->v_text[magic_cookie_glitch > 0 ? magic_cookie_glitch : 0]; - /* - * The odd code for magic_cookie_glitch==0 is to avoid - * putting the invisible glitch character on the next line. - * (Hazeltine executive 80 model 30) - */ - cp2 = &vvp->v_text[ncol - (magic_cookie_glitch >= 0 ? - (magic_cookie_glitch != 0 ? magic_cookie_glitch : 1) : 0)]; -#else - cp1 = &vvp->v_text[0]; - cp2 = &vvp->v_text[ncol]; -#endif - while (cp1 != cp2) { - ttputc(*cp1++); - ++ttcol; - } -#ifndef MOVE_STANDOUT - ttcolor(CTEXT); -#endif - return; - } - cp1 = &vvp->v_text[0]; /* Compute left match. */ - cp2 = &pvp->v_text[0]; - while (cp1 != &vvp->v_text[ncol] && cp1[0] == cp2[0]) { - ++cp1; - ++cp2; - } - if (cp1 == &vvp->v_text[ncol]) /* All equal. */ - return; - nbflag = FALSE; - cp3 = &vvp->v_text[ncol]; /* Compute right match. */ - cp4 = &pvp->v_text[ncol]; - while (cp3[-1] == cp4[-1]) { - --cp3; - --cp4; - if (cp3[0] != ' ') /* Note non-blanks in */ - nbflag = TRUE; /* the right match. */ - } - cp5 = cp3; /* Is erase good? */ - if (nbflag == FALSE && vvp->v_color == CTEXT) { - while (cp5 != cp1 && cp5[-1] == ' ') - --cp5; - /* Alcyon hack */ - if ((int) (cp3 - cp5) <= tceeol) - cp5 = cp3; - } - /* Alcyon hack */ - ttmove(row, (int) (cp1 - &vvp->v_text[0])); -#ifdef STANDOUT_GLITCH - if (vvp->v_color != CTEXT && magic_cookie_glitch > 0) { - if (cp1 < &vvp->v_text[magic_cookie_glitch]) - cp1 = &vvp->v_text[magic_cookie_glitch]; - if (cp5 > &vvp->v_text[ncol - magic_cookie_glitch]) - cp5 = &vvp->v_text[ncol - magic_cookie_glitch]; - } else if (magic_cookie_glitch < 0) -#endif - ttcolor(vvp->v_color); - while (cp1 != cp5) { - ttputc(*cp1++); - ++ttcol; - } - if (cp5 != cp3) /* Do erase. */ - tteeol(); -} - -/* - * Redisplay the mode line for the window pointed to by the "wp". - * This is the only routine that has any idea of how the mode line is - * formatted. You can change the modeline format by hacking at this - * routine. Called by "update" any time there is a dirty window. Note - * that if STANDOUT_GLITCH is defined, first and last magic_cookie_glitch - * characters may never be seen. - */ -void -modeline(struct mgwin *wp) -{ - int n, md; - struct buffer *bp; - char sl[21]; /* Overkill. Space for 2^64 in base 10. */ - int len; - - n = wp->w_toprow + wp->w_ntrows; /* Location. */ - vscreen[n]->v_color = CMODE; /* Mode line color. */ - vscreen[n]->v_flag |= (VFCHG | VFHBAD); /* Recompute, display. */ - vtmove(n, 0); /* Seek to right line. */ - bp = wp->w_bufp; - vtputc('-'); - vtputc('-'); - if ((bp->b_flag & BFREADONLY) != 0) { - vtputc('%'); - if ((bp->b_flag & BFCHG) != 0) - vtputc('*'); - else - vtputc('%'); - } else if ((bp->b_flag & BFCHG) != 0) { /* "*" if changed. */ - vtputc('*'); - vtputc('*'); - } else { - vtputc('-'); - vtputc('-'); - } - vtputc('-'); - n = 5; - n += vtputs("Mg: "); - if (bp->b_bname[0] != '\0') - n += vtputs(&(bp->b_bname[0])); - while (n < 42) { /* Pad out with blanks. */ - vtputc(' '); - ++n; - } - vtputc('('); - ++n; - for (md = 0; ; ) { - n += vtputs(bp->b_modes[md]->p_name); - if (++md > bp->b_nmodes) - break; - vtputc('-'); - ++n; - } - /* XXX These should eventually move to a real mode */ - if (macrodef == TRUE) - n += vtputs("-def"); - if (globalwd == TRUE) - n += vtputs("-gwd"); - vtputc(')'); - ++n; - - if (linenos) { - len = snprintf(sl, sizeof(sl), "--L%d--C%d", wp->w_dotline, - getcolpos()); - if (len < sizeof(sl) && len != -1) - n += vtputs(sl); - } - - while (n < ncol) { /* Pad out. */ - vtputc('-'); - ++n; - } -} - -/* - * Output a string to the mode line, report how long it was. - */ -int -vtputs(const char *s) -{ - int n = 0; - - while (*s != '\0') { - vtputc(*s++); - ++n; - } - return (n); -} - -/* - * Compute the hash code for the line pointed to by the "vp". - * Recompute it if necessary. Also set the approximate redisplay - * cost. The validity of the hash code is marked by a flag bit. - * The cost understand the advantages of erase to end of line. - * Tuned for the VAX by Bob McNamara; better than it used to be on - * just about any machine. - */ -void -hash(struct video *vp) -{ - int i, n; - char *s; - - if ((vp->v_flag & VFHBAD) != 0) { /* Hash bad. */ - s = &vp->v_text[ncol - 1]; - for (i = ncol; i != 0; --i, --s) - if (*s != ' ') - break; - n = ncol - i; /* Erase cheaper? */ - if (n > tceeol) - n = tceeol; - vp->v_cost = i + n; /* Bytes + blanks. */ - for (n = 0; i != 0; --i, --s) - n = (n << 5) + n + *s; - vp->v_hash = n; /* Hash code. */ - vp->v_flag &= ~VFHBAD; /* Flag as all done. */ - } -} - -/* - * Compute the Insert-Delete - * cost matrix. The dynamic programming algorithm - * described by James Gosling is used. This code assumes - * that the line above the echo line is the last line involved - * in the scroll region. This is easy to arrange on the VT100 - * because of the scrolling region. The "offs" is the origin 0 - * offset of the first row in the virtual/physical screen that - * is being updated; the "size" is the length of the chunk of - * screen being updated. For a full screen update, use offs=0 - * and size=nrow-1. - * - * Older versions of this code implemented the score matrix by - * a two dimensional array of SCORE nodes. This put all kinds of - * multiply instructions in the code! This version is written to - * use a linear array and pointers, and contains no multiplication - * at all. The code has been carefully looked at on the VAX, with - * only marginal checking on other machines for efficiency. In - * fact, this has been tuned twice! Bob McNamara tuned it even - * more for the VAX, which is a big issue for him because of - * the 66 line X displays. - * - * On some machines, replacing the "for (i=1; i<=size; ++i)" with - * i = 1; do { } while (++i <=size)" will make the code quite a - * bit better; but it looks ugly. - */ -void -setscores(int offs, int size) -{ - struct score *sp; - struct score *sp1; - struct video **vp, **pp; - struct video **vbase, **pbase; - int tempcost; - int bestcost; - int j, i; - - vbase = &vscreen[offs - 1]; /* By hand CSE's. */ - pbase = &pscreen[offs - 1]; - score[0].s_itrace = 0; /* [0, 0] */ - score[0].s_jtrace = 0; - score[0].s_cost = 0; - sp = &score[1]; /* Row 0, inserts. */ - tempcost = 0; - vp = &vbase[1]; - for (j = 1; j <= size; ++j) { - sp->s_itrace = 0; - sp->s_jtrace = j - 1; - tempcost += tcinsl; - tempcost += (*vp)->v_cost; - sp->s_cost = tempcost; - ++vp; - ++sp; - } - sp = &score[nrow]; /* Column 0, deletes. */ - tempcost = 0; - for (i = 1; i <= size; ++i) { - sp->s_itrace = i - 1; - sp->s_jtrace = 0; - tempcost += tcdell; - sp->s_cost = tempcost; - sp += nrow; - } - sp1 = &score[nrow + 1]; /* [1, 1]. */ - pp = &pbase[1]; - for (i = 1; i <= size; ++i) { - sp = sp1; - vp = &vbase[1]; - for (j = 1; j <= size; ++j) { - sp->s_itrace = i - 1; - sp->s_jtrace = j; - bestcost = (sp - nrow)->s_cost; - if (j != size) /* Cd(A[i])=0 @ Dis. */ - bestcost += tcdell; - tempcost = (sp - 1)->s_cost; - tempcost += (*vp)->v_cost; - if (i != size) /* Ci(B[j])=0 @ Dsj. */ - tempcost += tcinsl; - if (tempcost < bestcost) { - sp->s_itrace = i; - sp->s_jtrace = j - 1; - bestcost = tempcost; - } - tempcost = (sp - nrow - 1)->s_cost; - if ((*pp)->v_color != (*vp)->v_color - || (*pp)->v_hash != (*vp)->v_hash) - tempcost += (*vp)->v_cost; - if (tempcost < bestcost) { - sp->s_itrace = i - 1; - sp->s_jtrace = j - 1; - bestcost = tempcost; - } - sp->s_cost = bestcost; - ++sp; /* Next column. */ - ++vp; - } - ++pp; - sp1 += nrow; /* Next row. */ - } -} - -/* - * Trace back through the dynamic programming cost - * matrix, and update the screen using an optimal sequence - * of redraws, insert lines, and delete lines. The "offs" is - * the origin 0 offset of the chunk of the screen we are about to - * update. The "i" and "j" are always started in the lower right - * corner of the matrix, and imply the size of the screen. - * A full screen traceback is called with offs=0 and i=j=nrow-1. - * There is some do-it-yourself double subscripting here, - * which is acceptable because this routine is much less compute - * intensive then the code that builds the score matrix! - */ -void -traceback(int offs, int size, int i, int j) -{ - int itrace, jtrace; - int k; - int ninsl, ndraw, ndell; - - if (i == 0 && j == 0) /* End of update. */ - return; - itrace = score[(nrow * i) + j].s_itrace; - jtrace = score[(nrow * i) + j].s_jtrace; - if (itrace == i) { /* [i, j-1] */ - ninsl = 0; /* Collect inserts. */ - if (i != size) - ninsl = 1; - ndraw = 1; - while (itrace != 0 || jtrace != 0) { - if (score[(nrow * itrace) + jtrace].s_itrace != itrace) - break; - jtrace = score[(nrow * itrace) + jtrace].s_jtrace; - if (i != size) - ++ninsl; - ++ndraw; - } - traceback(offs, size, itrace, jtrace); - if (ninsl != 0) { - ttcolor(CTEXT); - ttinsl(offs + j - ninsl, offs + size - 1, ninsl); - } - do { /* B[j], A[j] blank. */ - k = offs + j - ndraw; - uline(k, vscreen[k], &blanks); - } while (--ndraw); - return; - } - if (jtrace == j) { /* [i-1, j] */ - ndell = 0; /* Collect deletes. */ - if (j != size) - ndell = 1; - while (itrace != 0 || jtrace != 0) { - if (score[(nrow * itrace) + jtrace].s_jtrace != jtrace) - break; - itrace = score[(nrow * itrace) + jtrace].s_itrace; - if (j != size) - ++ndell; - } - if (ndell != 0) { - ttcolor(CTEXT); - ttdell(offs + i - ndell, offs + size - 1, ndell); - } - traceback(offs, size, itrace, jtrace); - return; - } - traceback(offs, size, itrace, jtrace); - k = offs + j - 1; - uline(k, vscreen[k], pscreen[offs + i - 1]); -} diff --git a/mg/echo.c b/mg/echo.c deleted file mode 100644 index ce173f6..0000000 --- a/mg/echo.c +++ /dev/null @@ -1,964 +0,0 @@ -/* $OpenBSD: echo.c,v 1.50 2012/04/12 04:47:59 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Echo line reading and writing. - * - * Common routines for reading and writing characters in the echo line area - * of the display screen. Used by the entire known universe. - */ - -#include "def.h" -#include "key.h" -#include "macro.h" - -#include "funmap.h" - -#include -#include - -static char *veread(const char *, char *, size_t, int, va_list); -static int complt(int, int, char *, size_t, int, int *); -static int complt_list(int, char *, int); -static void eformat(const char *, va_list); -static void eputi(int, int); -static void eputl(long, int); -static void eputs(const char *); -static void eputc(char); -static struct list *copy_list(struct list *); - -int epresf = FALSE; /* stuff in echo line flag */ - -/* - * Erase the echo line. - */ -void -eerase(void) -{ - ttcolor(CTEXT); - ttmove(nrow - 1, 0); - tteeol(); - ttflush(); - epresf = FALSE; -} - -/* - * 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 */ -} - -/* - * Like eyorn, but for more important questions. User must type all of - * "yes" or "no" and the trailing newline. - */ -int -eyesno(const char *sp) -{ - char buf[64], *rep; - - if (inmacro) - return (TRUE); - - rep = eread("%s? (yes or no) ", buf, sizeof(buf), - EFNUL | EFNEW | EFCR, sp); - for (;;) { - if (rep == NULL) - return (ABORT); - if (rep[0] != '\0') { - if (macrodef) { - struct line *lp = maclcur; - - maclcur = lp->l_bp; - maclcur->l_fp = lp->l_fp; - free(lp); - } - if ((rep[0] == 'y' || rep[0] == 'Y') && - (rep[1] == 'e' || rep[1] == 'E') && - (rep[2] == 's' || rep[2] == 'S') && - (rep[3] == '\0')) - return (TRUE); - if ((rep[0] == 'n' || rep[0] == 'N') && - (rep[1] == 'o' || rep[0] == 'O') && - (rep[2] == '\0')) - return (FALSE); - } - rep = eread("Please answer yes or no. %s? (yes or no) ", - buf, sizeof(buf), EFNUL | EFNEW | EFCR, sp); - } - /* NOTREACHED */ -} - -/* - * This is the general "read input from the echo line" routine. The basic - * idea is that the prompt string "prompt" is written to the echo line, and - * a one line reply is read back into the supplied "buf" (with maximum - * length "len"). - * XXX: When checking for an empty return value, always check rep, *not* buf - * as buf may be freed in pathological cases. - */ -/* VARARGS */ -char * -eread(const char *fmt, char *buf, size_t nbuf, int flag, ...) -{ - va_list ap; - char *rep; - - va_start(ap, flag); - rep = veread(fmt, buf, nbuf, flag, ap); - va_end(ap); - return (rep); -} - -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 == ' ' || 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(); - y = buf[cpos]; - 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); -} - -/* - * Do completion on a list of objects. - * c is SPACE, TAB, or CR - * return TRUE if matched (or partially matched) - * FALSE is result is ambiguous, - * ABORT on error. - */ -static int -complt(int flags, int c, char *buf, size_t nbuf, int cpos, int *nx) -{ - struct list *lh, *lh2; - struct list *wholelist = NULL; - int i, nxtra, nhits, bxtra, msglen, nshown; - int wflag = FALSE; - char *msg; - - lh = lh2 = NULL; - - if ((flags & EFFUNC) != 0) { - buf[cpos] = '\0'; - wholelist = lh = complete_function_list(buf); - } else if ((flags & EFBUF) != 0) { - lh = &(bheadp->b_list); - } else if ((flags & EFFILE) != 0) { - buf[cpos] = '\0'; - wholelist = lh = make_file_list(buf); - } else - panic("broken complt call: flags"); - - if (c == ' ') - wflag = TRUE; - else if (c != '\t' && c != CCHR('M')) - panic("broken complt call: c"); - - nhits = 0; - nxtra = HUGE; - - for (; lh != NULL; lh = lh->l_next) { - if (memcmp(buf, lh->l_name, cpos) != 0) - continue; - if (nhits == 0) - lh2 = lh; - ++nhits; - if (lh->l_name[cpos] == '\0') - nxtra = -1; /* exact match */ - else { - bxtra = getxtra(lh, lh2, cpos, wflag); - if (bxtra < nxtra) - nxtra = bxtra; - lh2 = lh; - } - } - if (nhits == 0) - msg = " [No match]"; - else if (nhits > 1 && nxtra == 0) - msg = " [Ambiguous. Ctrl-G to cancel]"; - else { - /* - * Being lazy - ought to check length, but all things - * autocompleted have known types/lengths. - */ - if (nxtra < 0 && nhits > 1 && c == ' ') - nxtra = 1; /* ??? */ - for (i = 0; i < nxtra && cpos < nbuf; ++i) { - buf[cpos] = lh2->l_name[cpos]; - eputc(buf[cpos++]); - } - /* XXX should grow nbuf */ - ttflush(); - free_file_list(wholelist); - *nx = nxtra; - if (nxtra < 0 && c != CCHR('M')) /* exact */ - *nx = 0; - return (TRUE); - } - - /* - * wholelist is NULL if we are doing buffers. Want to free lists - * that were created for us, but not the buffer list! - */ - free_file_list(wholelist); - - /* Set up backspaces, etc., being mindful of echo line limit. */ - msglen = strlen(msg); - nshown = (ttcol + msglen + 2 > ncol) ? - ncol - ttcol - 2 : msglen; - eputs(msg); - ttcol -= (i = nshown); /* update ttcol! */ - while (i--) /* move back before msg */ - ttputc('\b'); - ttflush(); /* display to user */ - i = nshown; - while (i--) /* blank out on next flush */ - eputc(' '); - ttcol -= (i = nshown); /* update ttcol on BS's */ - while (i--) - ttputc('\b'); /* update ttcol again! */ - *nx = nxtra; - return ((nhits > 0) ? TRUE : FALSE); -} - -/* - * Do completion on a list of objects, listing instead of completing. - */ -static int -complt_list(int flags, char *buf, int cpos) -{ - struct list *lh, *lh2, *lh3; - struct list *wholelist = NULL; - struct buffer *bp; - int i, maxwidth, width; - int preflen = 0; - int oldrow = ttrow; - int oldcol = ttcol; - int oldhue = tthue; - char *linebuf; - size_t linesize, len; - char *cp; - - lh = NULL; - - ttflush(); - - /* The results are put into a completion buffer. */ - bp = bfind("*Completions*", TRUE); - if (bclear(bp) == FALSE) - return (FALSE); - - /* - * First get the list of objects. This list may contain only - * the ones that complete what has been typed, or may be the - * whole list of all objects of this type. They are filtered - * later in any case. Set wholelist if the list has been - * cons'ed up just for us, so we can free it later. We have - * to copy the buffer list for this function even though we - * didn't for complt. The sorting code does destructive - * changes to the list, which we don't want to happen to the - * main buffer list! - */ - if ((flags & EFBUF) != 0) - wholelist = lh = copy_list(&(bheadp->b_list)); - else if ((flags & EFFUNC) != 0) { - buf[cpos] = '\0'; - wholelist = lh = complete_function_list(buf); - } else if ((flags & EFFILE) != 0) { - buf[cpos] = '\0'; - wholelist = lh = make_file_list(buf); - /* - * We don't want to display stuff up to the / for file - * names preflen is the list of a prefix of what the - * user typed that should not be displayed. - */ - cp = strrchr(buf, '/'); - if (cp) - preflen = cp - buf + 1; - } else - panic("broken complt call: flags"); - - /* - * Sort the list, since users expect to see it in alphabetic - * order. - */ - lh2 = lh; - while (lh2 != NULL) { - lh3 = lh2->l_next; - while (lh3 != NULL) { - if (strcmp(lh2->l_name, lh3->l_name) > 0) { - cp = lh2->l_name; - lh2->l_name = lh3->l_name; - lh3->l_name = cp; - } - lh3 = lh3->l_next; - } - lh2 = lh2->l_next; - } - - /* - * First find max width of object to be displayed, so we can - * put several on a line. - */ - maxwidth = 0; - lh2 = lh; - while (lh2 != NULL) { - for (i = 0; i < cpos; ++i) { - if (buf[i] != lh2->l_name[i]) - break; - } - if (i == cpos) { - width = strlen(lh2->l_name); - if (width > maxwidth) - maxwidth = width; - } - lh2 = lh2->l_next; - } - maxwidth += 1 - preflen; - - /* - * Now do the display. Objects are written into linebuf until - * it fills, and then put into the help buffer. - */ - linesize = MAX(ncol, maxwidth) + 1; - if ((linebuf = malloc(linesize)) == NULL) - return (FALSE); - width = 0; - - /* - * We're going to strlcat() into the buffer, so it has to be - * NUL terminated. - */ - linebuf[0] = '\0'; - for (lh2 = lh; lh2 != NULL; lh2 = lh2->l_next) { - for (i = 0; i < cpos; ++i) { - if (buf[i] != lh2->l_name[i]) - break; - } - /* if we have a match */ - if (i == cpos) { - /* if it wraps */ - if ((width + maxwidth) > ncol) { - addline(bp, linebuf); - linebuf[0] = '\0'; - width = 0; - } - len = strlcat(linebuf, lh2->l_name + preflen, - linesize); - width += maxwidth; - if (len < width && width < linesize) { - /* pad so the objects nicely line up */ - memset(linebuf + len, ' ', - maxwidth - strlen(lh2->l_name + preflen)); - linebuf[width] = '\0'; - } - } - } - if (width > 0) - addline(bp, linebuf); - free(linebuf); - - /* - * Note that we free lists only if they are put in wholelist lists - * that were built just for us should be freed. However when we use - * the buffer list, obviously we don't want it freed. - */ - free_file_list(wholelist); - popbuftop(bp, WEPHEM); /* split the screen and put up the help - * buffer */ - update(); /* needed to make the new stuff actually - * appear */ - ttmove(oldrow, oldcol); /* update leaves cursor in arbitrary place */ - ttcolor(oldhue); /* with arbitrary color */ - ttflush(); - return (0); -} - -/* - * The "lp1" and "lp2" point to list structures. The "cpos" is a horizontal - * position in the name. Return the longest block of characters that can be - * autocompleted at this point. Sometimes the two symbols are the same, but - * this is normal. - */ -int -getxtra(struct list *lp1, struct list *lp2, int cpos, int wflag) -{ - int i; - - i = cpos; - for (;;) { - if (lp1->l_name[i] != lp2->l_name[i]) - break; - if (lp1->l_name[i] == '\0') - break; - ++i; - if (wflag && !ISWORD(lp1->l_name[i - 1])) - break; - } - return (i - cpos); -} - -/* - * Special "printf" for the echo line. Each call to "ewprintf" starts a - * new line in the echo area, and ends with an erase to end of the echo - * line. The formatting is done by a call to the standard formatting - * routine. - */ -/* VARARGS */ -void -ewprintf(const char *fmt, ...) -{ - va_list ap; - - if (inmacro) - return; - - va_start(ap, fmt); - ttcolor(CTEXT); - ttmove(nrow - 1, 0); - eformat(fmt, ap); - va_end(ap); - tteeol(); - ttflush(); - epresf = TRUE; -} - -/* - * Printf style formatting. This is called by both "ewprintf" and "ereply" - * to provide formatting services to their clients. The move to the start - * of the echo line, and the erase to the end of the echo line, is done by - * the caller. - * %c prints the "name" of the supplied character. - * %k prints the name of the current key (and takes no arguments). - * %d prints a decimal integer - * %o prints an octal integer - * %p prints a pointer - * %s prints a string - * %ld prints a long word - * Anything else is echoed verbatim - */ -static void -eformat(const char *fp, va_list ap) -{ - char kname[NKNAME], tmp[100], *cp; - int c; - - while ((c = *fp++) != '\0') { - if (c != '%') - eputc(c); - else { - c = *fp++; - switch (c) { - case 'c': - getkeyname(kname, sizeof(kname), - va_arg(ap, int)); - eputs(kname); - break; - - case 'k': - for (cp = kname, c = 0; c < key.k_count; c++) { - if (c) - *cp++ = ' '; - cp = getkeyname(cp, sizeof(kname) - - (cp - kname) - 1, key.k_chars[c]); - } - eputs(kname); - break; - - case 'd': - eputi(va_arg(ap, int), 10); - break; - - case 'o': - eputi(va_arg(ap, int), 8); - break; - - case 'p': - snprintf(tmp, sizeof(tmp), "%p", - va_arg(ap, void *)); - eputs(tmp); - break; - - case 's': - eputs(va_arg(ap, char *)); - break; - - case 'l': - /* explicit longword */ - c = *fp++; - switch (c) { - case 'd': - eputl(va_arg(ap, long), 10); - break; - default: - eputc(c); - break; - } - break; - - default: - eputc(c); - } - } - } -} - -/* - * Put integer, in radix "r". - */ -static void -eputi(int i, int r) -{ - int q; - - if (i < 0) { - eputc('-'); - i = -i; - } - if ((q = i / r) != 0) - eputi(q, r); - eputc(i % r + '0'); -} - -/* - * Put long, in radix "r". - */ -static void -eputl(long l, int r) -{ - long q; - - if (l < 0) { - eputc('-'); - l = -l; - } - if ((q = l / r) != 0) - eputl(q, r); - eputc((int)(l % r) + '0'); -} - -/* - * Put string. - */ -static void -eputs(const char *s) -{ - int c; - - while ((c = *s++) != '\0') - eputc(c); -} - -/* - * Put character. Watch for control characters, and for the line getting - * too long. - */ -static void -eputc(char c) -{ - if (ttcol + 2 < ncol) { - if (ISCTRL(c)) { - eputc('^'); - c = CCHR(c); - } - ttputc(c); - ++ttcol; - } -} - -void -free_file_list(struct list *lp) -{ - struct list *next; - - while (lp) { - next = lp->l_next; - free(lp->l_name); - free(lp); - lp = next; - } -} - -static struct list * -copy_list(struct list *lp) -{ - struct list *current, *last, *nxt; - - last = NULL; - while (lp) { - current = malloc(sizeof(struct list)); - if (current == NULL) { - /* Free what we have allocated so far */ - for (current = last; current; current = nxt) { - nxt = current->l_next; - free(current->l_name); - free(current); - } - return (NULL); - } - current->l_next = last; - current->l_name = strdup(lp->l_name); - last = current; - lp = lp->l_next; - } - return (last); -} diff --git a/mg/extend.c b/mg/extend.c deleted file mode 100644 index 2f47de6..0000000 --- a/mg/extend.c +++ /dev/null @@ -1,963 +0,0 @@ -/* $OpenBSD: extend.c,v 1.53 2012/05/25 04:56:58 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Extended (M-X) commands, rebinding, and startup file processing. - */ -#include "chrdef.h" -#include "def.h" -#include "kbd.h" -#include "funmap.h" - -#include -#include - -#include "macro.h" - -#ifdef FKEYS -#include "key.h" -#ifndef BINDKEY -#define BINDKEY /* bindkey is used by FKEYS startup code */ -#endif /* !BINDKEY */ -#endif /* FKEYS */ - -#include - -static int remap(KEYMAP *, int, PF, KEYMAP *); -static KEYMAP *reallocmap(KEYMAP *); -static void fixmap(KEYMAP *, KEYMAP *, KEYMAP *); -static int dobind(KEYMAP *, const char *, int); -static char *skipwhite(char *); -static char *parsetoken(char *); -#ifdef BINDKEY -static int bindkey(KEYMAP **, const char *, KCHAR *, int); -#endif /* BINDKEY */ - -/* - * Insert a string, mainly for use from macros (created by selfinsert). - */ -/* ARGSUSED */ -int -insert(int f, int n) -{ - char buf[128], *bufp, *cp; - int count, c; - - if (inmacro) { - while (--n >= 0) { - for (count = 0; count < maclcur->l_used; count++) { - if ((((c = maclcur->l_text[count]) == '\n') - ? lnewline() : linsert(1, c)) != TRUE) - return (FALSE); - } - } - maclcur = maclcur->l_fp; - return (TRUE); - } - if (n == 1) - /* CFINS means selfinsert can tack on the end */ - thisflag |= CFINS; - - if ((bufp = eread("Insert: ", buf, sizeof(buf), EFNEW)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - while (--n >= 0) { - cp = buf; - while (*cp) { - if (((*cp == '\n') ? lnewline() : linsert(1, *cp)) - != TRUE) - return (FALSE); - cp++; - } - } - return (TRUE); -} - -/* - * Bind a key to a function. Cases range from the trivial (replacing an - * existing binding) to the extremely complex (creating a new prefix in a - * map_element that already has one, so the map_element must be split, - * but the keymap doesn't have enough room for another map_element, so - * the keymap is reallocated). No attempt is made to reclaim space no - * longer used, if this is a problem flags must be added to indicate - * malloced versus static storage in both keymaps and map_elements. - * Structure assignments would come in real handy, but K&R based compilers - * don't have them. Care is taken so running out of memory will leave - * the keymap in a usable state. - * Parameters are: - * curmap: pointer to the map being changed - * c: character being changed - * funct: function being changed to - * pref_map: if funct==NULL, map to bind to or NULL for new - */ -static int -remap(KEYMAP *curmap, int c, PF funct, KEYMAP *pref_map) -{ - int i, n1, n2, nold; - KEYMAP *mp, *newmap; - PF *pfp; - struct map_element *mep; - - if (ele >= &curmap->map_element[curmap->map_num] || c < ele->k_base) { - if (ele > &curmap->map_element[0] && (funct != NULL || - (ele - 1)->k_prefmap == NULL)) - n1 = c - (ele - 1)->k_num; - else - n1 = HUGE; - if (ele < &curmap->map_element[curmap->map_num] && - (funct != NULL || ele->k_prefmap == NULL)) - n2 = ele->k_base - c; - else - n2 = HUGE; - if (n1 <= MAPELEDEF && n1 <= n2) { - ele--; - if ((pfp = calloc(c - ele->k_base + 1, - sizeof(PF))) == NULL) { - ewprintf("Out of memory"); - return (FALSE); - } - nold = ele->k_num - ele->k_base + 1; - for (i = 0; i < nold; i++) - pfp[i] = ele->k_funcp[i]; - while (--n1) - pfp[i++] = curmap->map_default; - pfp[i] = funct; - ele->k_num = c; - ele->k_funcp = pfp; - } else if (n2 <= MAPELEDEF) { - if ((pfp = calloc(ele->k_num - c + 1, - sizeof(PF))) == NULL) { - ewprintf("Out of memory"); - return (FALSE); - } - nold = ele->k_num - ele->k_base + 1; - for (i = 0; i < nold; i++) - pfp[i + n2] = ele->k_funcp[i]; - while (--n2) - pfp[n2] = curmap->map_default; - pfp[0] = funct; - ele->k_base = c; - ele->k_funcp = pfp; - } else { - if (curmap->map_num >= curmap->map_max) { - if ((newmap = reallocmap(curmap)) == NULL) - return (FALSE); - curmap = newmap; - } - if ((pfp = malloc(sizeof(PF))) == NULL) { - ewprintf("Out of memory"); - return (FALSE); - } - pfp[0] = funct; - for (mep = &curmap->map_element[curmap->map_num]; - mep > ele; mep--) { - mep->k_base = (mep - 1)->k_base; - mep->k_num = (mep - 1)->k_num; - mep->k_funcp = (mep - 1)->k_funcp; - mep->k_prefmap = (mep - 1)->k_prefmap; - } - ele->k_base = c; - ele->k_num = c; - ele->k_funcp = pfp; - ele->k_prefmap = NULL; - curmap->map_num++; - } - if (funct == NULL) { - if (pref_map != NULL) - ele->k_prefmap = pref_map; - else { - if ((mp = malloc(sizeof(KEYMAP) + - (MAPINIT - 1) * sizeof(struct map_element))) == NULL) { - ewprintf("Out of memory"); - ele->k_funcp[c - ele->k_base] = - curmap->map_default; - return (FALSE); - } - mp->map_num = 0; - mp->map_max = MAPINIT; - mp->map_default = rescan; - ele->k_prefmap = mp; - } - } - } else { - n1 = c - ele->k_base; - if (ele->k_funcp[n1] == funct && (funct != NULL || - pref_map == NULL || pref_map == ele->k_prefmap)) - /* no change */ - return (TRUE); - if (funct != NULL || ele->k_prefmap == NULL) { - if (ele->k_funcp[n1] == NULL) - ele->k_prefmap = NULL; - /* easy case */ - ele->k_funcp[n1] = funct; - if (funct == NULL) { - if (pref_map != NULL) - ele->k_prefmap = pref_map; - else { - if ((mp = malloc(sizeof(KEYMAP) + - (MAPINIT - 1) * - sizeof(struct map_element))) == NULL) { - ewprintf("Out of memory"); - ele->k_funcp[c - ele->k_base] = - curmap->map_default; - return (FALSE); - } - mp->map_num = 0; - mp->map_max = MAPINIT; - mp->map_default = rescan; - ele->k_prefmap = mp; - } - } - } else { - /* - * This case is the splits. - * Determine which side of the break c goes on - * 0 = after break; 1 = before break - */ - n2 = 1; - for (i = 0; n2 && i < n1; i++) - n2 &= ele->k_funcp[i] != NULL; - if (curmap->map_num >= curmap->map_max) { - if ((newmap = reallocmap(curmap)) == NULL) - return (FALSE); - curmap = newmap; - } - if ((pfp = calloc(ele->k_num - c + !n2, - sizeof(PF))) == NULL) { - ewprintf("Out of memory"); - return (FALSE); - } - ele->k_funcp[n1] = NULL; - for (i = n1 + n2; i <= ele->k_num - ele->k_base; i++) - pfp[i - n1 - n2] = ele->k_funcp[i]; - for (mep = &curmap->map_element[curmap->map_num]; - mep > ele; mep--) { - mep->k_base = (mep - 1)->k_base; - mep->k_num = (mep - 1)->k_num; - mep->k_funcp = (mep - 1)->k_funcp; - mep->k_prefmap = (mep - 1)->k_prefmap; - } - ele->k_num = c - !n2; - (ele + 1)->k_base = c + n2; - (ele + 1)->k_funcp = pfp; - ele += !n2; - ele->k_prefmap = NULL; - curmap->map_num++; - if (pref_map == NULL) { - if ((mp = malloc(sizeof(KEYMAP) + (MAPINIT - 1) - * sizeof(struct map_element))) == NULL) { - ewprintf("Out of memory"); - ele->k_funcp[c - ele->k_base] = - curmap->map_default; - return (FALSE); - } - mp->map_num = 0; - mp->map_max = MAPINIT; - mp->map_default = rescan; - ele->k_prefmap = mp; - } else - ele->k_prefmap = pref_map; - } - } - return (TRUE); -} - -/* - * Reallocate a keymap. Returns NULL (without trashing the current map) - * on failure. - */ -static KEYMAP * -reallocmap(KEYMAP *curmap) -{ - struct maps_s *mps; - KEYMAP *mp; - int i; - - if (curmap->map_max > SHRT_MAX - MAPGROW) { - ewprintf("keymap too large"); - return (NULL); - } - if ((mp = malloc(sizeof(KEYMAP) + (curmap->map_max + (MAPGROW - 1)) * - sizeof(struct map_element))) == NULL) { - ewprintf("Out of memory"); - return (NULL); - } - mp->map_num = curmap->map_num; - mp->map_max = curmap->map_max + MAPGROW; - mp->map_default = curmap->map_default; - for (i = curmap->map_num; i--;) { - mp->map_element[i].k_base = curmap->map_element[i].k_base; - mp->map_element[i].k_num = curmap->map_element[i].k_num; - mp->map_element[i].k_funcp = curmap->map_element[i].k_funcp; - mp->map_element[i].k_prefmap = curmap->map_element[i].k_prefmap; - } - for (mps = maps; mps != NULL; mps = mps->p_next) { - if (mps->p_map == curmap) - mps->p_map = mp; - else - fixmap(curmap, mp, mps->p_map); - } - ele = &mp->map_element[ele - &curmap->map_element[0]]; - return (mp); -} - -/* - * Fix references to a reallocated keymap (recursive). - */ -static void -fixmap(KEYMAP *curmap, KEYMAP *mp, KEYMAP *mt) -{ - int i; - - for (i = mt->map_num; i--;) { - if (mt->map_element[i].k_prefmap != NULL) { - if (mt->map_element[i].k_prefmap == curmap) - mt->map_element[i].k_prefmap = mp; - else - fixmap(curmap, mp, mt->map_element[i].k_prefmap); - } - } -} - -/* - * Do the input for local-set-key, global-set-key and define-key - * then call remap to do the work. - */ -static int -dobind(KEYMAP *curmap, const char *p, int unbind) -{ - KEYMAP *pref_map = NULL; - PF funct; - char bprompt[80], *bufp, *pep; - int c, s, n; - - if (macrodef) { - /* - * Keystrokes aren't collected. Not hard, but pretty useless. - * Would not work for function keys in any case. - */ - ewprintf("Can't rebind key in macro"); - return (FALSE); - } - if (inmacro) { - for (s = 0; s < maclcur->l_used - 1; s++) { - if (doscan(curmap, c = CHARMASK(maclcur->l_text[s]), &curmap) - != NULL) { - if (remap(curmap, c, NULL, NULL) - != TRUE) - return (FALSE); - } - } - (void)doscan(curmap, c = maclcur->l_text[s], NULL); - maclcur = maclcur->l_fp; - } else { - n = strlcpy(bprompt, p, sizeof(bprompt)); - if (n >= sizeof(bprompt)) - n = sizeof(bprompt) - 1; - pep = bprompt + n; - for (;;) { - ewprintf("%s", bprompt); - pep[-1] = ' '; - pep = getkeyname(pep, sizeof(bprompt) - - (pep - bprompt), c = getkey(FALSE)); - if (doscan(curmap, c, &curmap) != NULL) - break; - *pep++ = '-'; - *pep = '\0'; - } - } - if (unbind) - funct = rescan; - else { - if ((bufp = eread("%s to command: ", bprompt, sizeof(bprompt), - EFFUNC | EFNEW, bprompt)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - if (((funct = name_function(bprompt)) == NULL) ? - (pref_map = name_map(bprompt)) == NULL : funct == NULL) { - ewprintf("[No match]"); - return (FALSE); - } - } - return (remap(curmap, c, funct, pref_map)); -} - -/* - * bindkey: bind key sequence to a function in the specified map. Used by - * excline so it can bind function keys. To close to release to change - * calling sequence, should just pass KEYMAP *curmap rather than - * KEYMAP **mapp. - */ -#ifdef BINDKEY -static int -bindkey(KEYMAP **mapp, const char *fname, KCHAR *keys, int kcount) -{ - KEYMAP *curmap = *mapp; - KEYMAP *pref_map = NULL; - PF funct; - int c; - - if (fname == NULL) - funct = rescan; - else if (((funct = name_function(fname)) == NULL) ? - (pref_map = name_map(fname)) == NULL : funct == NULL) { - ewprintf("[No match: %s]", fname); - return (FALSE); - } - while (--kcount) { - if (doscan(curmap, c = *keys++, &curmap) != NULL) { - if (remap(curmap, c, NULL, NULL) != TRUE) - return (FALSE); - /* - * XXX - Bizzarreness. remap creates an empty KEYMAP - * that the last key is supposed to point to. - */ - curmap = ele->k_prefmap; - } - } - (void)doscan(curmap, c = *keys, NULL); - return (remap(curmap, c, funct, pref_map)); -} - -#ifdef FKEYS -/* - * Wrapper for bindkey() that converts escapes. - */ -int -dobindkey(KEYMAP *map, const char *func, const char *str) -{ - int i; - - for (i = 0; *str && i < MAXKEY; i++) { - /* XXX - convert numbers w/ strol()? */ - if (*str == '^' && *(str + 1) != '\0') { - key.k_chars[i] = CCHR(toupper(*++str)); - } else if (*str == '\\' && *(str + 1) != '\0') { - switch (*++str) { - case '^': - key.k_chars[i] = '^'; - break; - case 't': - case 'T': - key.k_chars[i] = '\t'; - break; - case 'n': - case 'N': - key.k_chars[i] = '\n'; - break; - case 'r': - case 'R': - key.k_chars[i] = '\r'; - break; - case 'e': - case 'E': - key.k_chars[i] = CCHR('['); - break; - case '\\': - key.k_chars[i] = '\\'; - break; - } - } else - key.k_chars[i] = *str; - str++; - } - key.k_count = i; - return (bindkey(&map, func, key.k_chars, key.k_count)); -} -#endif /* FKEYS */ -#endif /* BINDKEY */ - -/* - * This function modifies the fundamental keyboard map. - */ -/* ARGSUSED */ -int -bindtokey(int f, int n) -{ - return (dobind(fundamental_map, "Global set key: ", FALSE)); -} - -/* - * This function modifies the current mode's keyboard map. - */ -/* ARGSUSED */ -int -localbind(int f, int n) -{ - return (dobind(curbp->b_modes[curbp->b_nmodes]->p_map, - "Local set key: ", FALSE)); -} - -/* - * This function redefines a key in any keymap. - */ -/* ARGSUSED */ -int -redefine_key(int f, int n) -{ - static char buf[48]; - char tmp[32], *bufp; - KEYMAP *mp; - - (void)strlcpy(buf, "Define key map: ", sizeof(buf)); - if ((bufp = eread(buf, tmp, sizeof(tmp), EFNEW)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - (void)strlcat(buf, tmp, sizeof(buf)); - if ((mp = name_map(tmp)) == NULL) { - ewprintf("Unknown map %s", tmp); - return (FALSE); - } - if (strlcat(buf, "key: ", sizeof(buf)) >= sizeof(buf)) - return (FALSE); - - return (dobind(mp, buf, FALSE)); -} - -/* ARGSUSED */ -int -unbindtokey(int f, int n) -{ - return (dobind(fundamental_map, "Global unset key: ", TRUE)); -} - -/* ARGSUSED */ -int -localunbind(int f, int n) -{ - return (dobind(curbp->b_modes[curbp->b_nmodes]->p_map, - "Local unset key: ", TRUE)); -} - -/* - * Extended command. Call the message line routine to read in the command - * name and apply autocompletion to it. When it comes back, look the name - * up in the symbol table and run the command if it is found. Print an - * error if there is anything wrong. - */ -int -extend(int f, int n) -{ - PF funct; - char xname[NXNAME], *bufp; - - if (!(f & FFARG)) - bufp = eread("M-x ", xname, NXNAME, EFNEW | EFFUNC); - else - bufp = eread("%d M-x ", xname, NXNAME, EFNEW | EFFUNC, n); - if (bufp == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - if ((funct = name_function(bufp)) != NULL) { - if (macrodef) { - struct line *lp = maclcur; - macro[macrocount - 1].m_funct = funct; - maclcur = lp->l_bp; - maclcur->l_fp = lp->l_fp; - free(lp); - } - return ((*funct)(f, n)); - } - ewprintf("[No match]"); - return (FALSE); -} - -/* - * Define the commands needed to do startup-file processing. - * This code is mostly a kludge just so we can get startup-file processing. - * - * If you're serious about having this code, you should rewrite it. - * To wit: - * It has lots of funny things in it to make the startup-file look - * like a GNU startup file; mostly dealing with parens and semicolons. - * This should all vanish. - * - * We define eval-expression because it's easy. It can make - * *-set-key or define-key set an arbitrary key sequence, so it isn't - * useless. - */ - -/* - * evalexpr - get one line from the user, and run it. - */ -/* ARGSUSED */ -int -evalexpr(int f, int n) -{ - char exbuf[128], *bufp; - - if ((bufp = eread("Eval: ", exbuf, sizeof(exbuf), - EFNEW | EFCR)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - return (excline(exbuf)); -} - -/* - * evalbuffer - evaluate the current buffer as line commands. Useful for - * testing startup files. - */ -/* ARGSUSED */ -int -evalbuffer(int f, int n) -{ - struct line *lp; - struct buffer *bp = curbp; - int s; - static char excbuf[128]; - - for (lp = bfirstlp(bp); lp != bp->b_headp; lp = lforw(lp)) { - if (llength(lp) >= 128) - return (FALSE); - (void)strncpy(excbuf, ltext(lp), llength(lp)); - - /* make sure it's terminated */ - excbuf[llength(lp)] = '\0'; - if ((s = excline(excbuf)) != TRUE) - return (s); - } - return (TRUE); -} - -/* - * evalfile - go get a file and evaluate it as line commands. You can - * go get your own startup file if need be. - */ -/* ARGSUSED */ -int -evalfile(int f, int n) -{ - char fname[NFILEN], *bufp; - - if ((bufp = eread("Load file: ", fname, NFILEN, - EFNEW | EFCR)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - return (load(fname)); -} - -/* - * load - go load the file name we got passed. - */ -int -load(const char *fname) -{ - int s = TRUE, line; - int nbytes = 0; - char excbuf[128]; - FILE *ffp; - - if ((fname = adjustname(fname, TRUE)) == NULL) - /* just to be careful */ - return (FALSE); - - if (ffropen(&ffp, fname, NULL) != FIOSUC) - return (FALSE); - - line = 0; - while ((s = ffgetline(ffp, excbuf, sizeof(excbuf) - 1, &nbytes)) - == FIOSUC) { - line++; - excbuf[nbytes] = '\0'; - if (excline(excbuf) != TRUE) { - s = FIOERR; - ewprintf("Error loading file %s at line %d", fname, line); - break; - } - } - (void)ffclose(ffp, NULL); - excbuf[nbytes] = '\0'; - if (s != FIOEOF || (nbytes && excline(excbuf) != TRUE)) - return (FALSE); - return (TRUE); -} - -/* - * excline - run a line from a load file or eval-expression. If FKEYS is - * defined, duplicate functionality of dobind so function key values don't - * have to fit in type char. - */ -int -excline(char *line) -{ - PF fp; - struct line *lp, *np; - int status, c, f, n; - char *funcp, *tmp; - char *argp = NULL; - long nl; -#ifdef FKEYS - int bind; - KEYMAP *curmap; -#define BINDARG 0 /* this arg is key to bind (local/global set key) */ -#define BINDNO 1 /* not binding or non-quoted BINDARG */ -#define BINDNEXT 2 /* next arg " (define-key) */ -#define BINDDO 3 /* already found key to bind */ -#define BINDEXT 1 /* space for trailing \0 */ -#else /* FKEYS */ -#define BINDEXT 0 -#endif /* FKEYS */ - - lp = NULL; - - if (macrodef || inmacro) { - ewprintf("Not now!"); - return (FALSE); - } - f = 0; - n = 1; - funcp = skipwhite(line); - if (*funcp == '\0') - return (TRUE); /* No error on blank lines */ - line = parsetoken(funcp); - if (*line != '\0') { - *line++ = '\0'; - line = skipwhite(line); - if (ISDIGIT(*line) || *line == '-') { - argp = line; - line = parsetoken(line); - } - } - if (argp != NULL) { - f = FFARG; - nl = strtol(argp, &tmp, 10); - if (*tmp != '\0') - return (FALSE); - if (nl >= INT_MAX || nl <= INT_MIN) - return (FALSE); - n = (int)nl; - } - if ((fp = name_function(funcp)) == NULL) { - ewprintf("Unknown function: %s", funcp); - return (FALSE); - } -#ifdef FKEYS - if (fp == bindtokey || fp == unbindtokey) { - bind = BINDARG; - curmap = fundamental_map; - } else if (fp == localbind || fp == localunbind) { - bind = BINDARG; - curmap = curbp->b_modes[curbp->b_nmodes]->p_map; - } else if (fp == redefine_key) - bind = BINDNEXT; - else - bind = BINDNO; -#endif /* FKEYS */ - /* Pack away all the args now... */ - if ((np = lalloc(0)) == FALSE) - return (FALSE); - np->l_fp = np->l_bp = maclcur = np; - while (*line != '\0') { - argp = skipwhite(line); - if (*argp == '\0') - break; - line = parsetoken(argp); - if (*argp != '"') { - if (*argp == '\'') - ++argp; - if ((lp = lalloc((int) (line - argp) + BINDEXT)) == - NULL) { - status = FALSE; - goto cleanup; - } - bcopy(argp, ltext(lp), (int)(line - argp)); -#ifdef FKEYS - /* don't count BINDEXT */ - lp->l_used--; - if (bind == BINDARG) - bind = BINDNO; -#endif /* FKEYS */ - } else { - /* quoted strings are special */ - ++argp; -#ifdef FKEYS - if (bind != BINDARG) { -#endif /* FKEYS */ - lp = lalloc((int)(line - argp) + BINDEXT); - if (lp == NULL) { - status = FALSE; - goto cleanup; - } - lp->l_used = 0; -#ifdef FKEYS - } else - key.k_count = 0; -#endif /* FKEYS */ - while (*argp != '"' && *argp != '\0') { - if (*argp != '\\') - c = *argp++; - else { - switch (*++argp) { - case 't': - case 'T': - c = CCHR('I'); - break; - case 'n': - case 'N': - c = CCHR('J'); - break; - case 'r': - case 'R': - c = CCHR('M'); - break; - case 'e': - case 'E': - c = CCHR('['); - break; - case '^': - /* - * split into two statements - * due to bug in OSK cpp - */ - c = CHARMASK(*++argp); - c = ISLOWER(c) ? - CCHR(TOUPPER(c)) : CCHR(c); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - c = *argp - '0'; - if (argp[1] <= '7' && - argp[1] >= '0') { - c <<= 3; - c += *++argp - '0'; - if (argp[1] <= '7' && - argp[1] >= '0') { - c <<= 3; - c += *++argp - - '0'; - } - } - break; -#ifdef FKEYS - case 'f': - case 'F': - c = *++argp - '0'; - if (ISDIGIT(argp[1])) { - c *= 10; - c += *++argp - '0'; - } - c += KFIRST; - break; -#endif /* FKEYS */ - default: - c = CHARMASK(*argp); - break; - } - argp++; - } -#ifdef FKEYS - if (bind == BINDARG) - key.k_chars[key.k_count++] = c; - else -#endif /* FKEYS */ - lp->l_text[lp->l_used++] = c; - } - if (*line) - line++; - } -#ifdef FKEYS - switch (bind) { - case BINDARG: - bind = BINDDO; - break; - case BINDNEXT: - lp->l_text[lp->l_used] = '\0'; - if ((curmap = name_map(lp->l_text)) == NULL) { - ewprintf("No such mode: %s", lp->l_text); - status = FALSE; - free(lp); - goto cleanup; - } - free(lp); - bind = BINDARG; - break; - default: -#endif /* FKEYS */ - lp->l_fp = np->l_fp; - lp->l_bp = np; - np->l_fp = lp; - np = lp; -#ifdef FKEYS - } -#endif /* FKEYS */ - } -#ifdef FKEYS - switch (bind) { - default: - ewprintf("Bad args to set key"); - status = FALSE; - break; - case BINDDO: - if (fp != unbindtokey && fp != localunbind) { - lp->l_text[lp->l_used] = '\0'; - status = bindkey(&curmap, lp->l_text, key.k_chars, - key.k_count); - } else - status = bindkey(&curmap, NULL, key.k_chars, - key.k_count); - break; - case BINDNO: -#endif /* FKEYS */ - inmacro = TRUE; - maclcur = maclcur->l_fp; - status = (*fp)(f, n); - inmacro = FALSE; -#ifdef FKEYS - } -#endif /* FKEYS */ -cleanup: - lp = maclcur->l_fp; - while (lp != maclcur) { - np = lp->l_fp; - free(lp); - lp = np; - } - free(lp); - return (status); -} - -/* - * a pair of utility functions for the above - */ -static char * -skipwhite(char *s) -{ - while (*s == ' ' || *s == '\t' || *s == ')' || *s == '(') - s++; - if (*s == ';') - *s = '\0'; - return (s); -} - -static char * -parsetoken(char *s) -{ - if (*s != '"') { - while (*s && *s != ' ' && *s != '\t' && *s != ')' && *s != '(') - s++; - if (*s == ';') - *s = '\0'; - } else - do { - /* - * Strings get special treatment. - * Beware: You can \ out the end of the string! - */ - if (*s == '\\') - ++s; - } while (*++s != '"' && *s != '\0'); - return (s); -} diff --git a/mg/file.c b/mg/file.c deleted file mode 100644 index acf64c1..0000000 --- a/mg/file.c +++ /dev/null @@ -1,715 +0,0 @@ -/* $OpenBSD: file.c,v 1.81 2012/06/18 09:19:21 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * File commands. - */ - -#include "def.h" - -#include - -#include - -size_t xdirname(char *, const char *, size_t); - -/* - * Insert a file into the current buffer. Real easy - just call the - * insertfile routine with the file name. - */ -/* ARGSUSED */ -int -fileinsert(int f, int n) -{ - char fname[NFILEN], *bufp, *adjf; - - if (getbufcwd(fname, sizeof(fname)) != TRUE) - fname[0] = '\0'; - bufp = eread("Insert file: ", fname, NFILEN, - EFNEW | EFCR | EFFILE | EFDEF); - if (bufp == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - adjf = adjustname(bufp, TRUE); - if (adjf == NULL) - return (FALSE); - return (insertfile(adjf, NULL, FALSE)); -} - -/* - * Select a file for editing. Look around to see if you can find the file - * in another buffer; if you can find it, just switch to the buffer. If - * you cannot find the file, create a new buffer, read in the text, and - * switch to the new buffer. - */ -/* ARGSUSED */ -int -filevisit(int f, int n) -{ - struct buffer *bp; - char fname[NFILEN], *bufp, *adjf; - int status; - - if (getbufcwd(fname, sizeof(fname)) != TRUE) - fname[0] = '\0'; - bufp = eread("Find file: ", fname, NFILEN, - EFNEW | EFCR | EFFILE | EFDEF); - if (bufp == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - adjf = adjustname(fname, TRUE); - if (adjf == NULL) - return (FALSE); - if ((bp = findbuffer(adjf)) == NULL) - return (FALSE); - curbp = bp; - if (showbuffer(bp, curwp, WFFULL) != TRUE) - return (FALSE); - if (bp->b_fname[0] == '\0') { - if ((status = readin(adjf)) != TRUE) - killbuffer(bp); - return (status); - } - return (TRUE); -} - -/* - * Replace the current file with an alternate one. Semantics for finding - * the replacement file are the same as 'filevisit', except the current - * buffer is killed before the switch. If the kill fails, or is aborted, - * revert to the original file. - */ -/* ARGSUSED */ -int -filevisitalt(int f, int n) -{ - struct buffer *bp; - char fname[NFILEN], *bufp, *adjf; - int status; - - if (getbufcwd(fname, sizeof(fname)) != TRUE) - fname[0] = '\0'; - bufp = eread("Find alternate file: ", fname, NFILEN, - EFNEW | EFCR | EFFILE | EFDEF); - if (bufp == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - - status = killbuffer(curbp); - if (status == ABORT || status == FALSE) - return (ABORT); - - adjf = adjustname(fname, TRUE); - if (adjf == NULL) - return (FALSE); - if ((bp = findbuffer(adjf)) == NULL) - return (FALSE); - curbp = bp; - if (showbuffer(bp, curwp, WFFULL) != TRUE) - return (FALSE); - if (bp->b_fname[0] == '\0') { - if ((status = readin(adjf)) != TRUE) - killbuffer(bp); - return (status); - } - return (TRUE); -} - -int -filevisitro(int f, int n) -{ - int error; - - error = filevisit(f, n); - if (error != TRUE) - return (error); - curbp->b_flag |= BFREADONLY; - return (TRUE); -} - -/* - * Pop to a file in the other window. Same as the last function, but uses - * popbuf instead of showbuffer. - */ -/* ARGSUSED */ -int -poptofile(int f, int n) -{ - struct buffer *bp; - struct mgwin *wp; - char fname[NFILEN], *adjf, *bufp; - int status; - - if (getbufcwd(fname, sizeof(fname)) != TRUE) - fname[0] = '\0'; - if ((bufp = eread("Find file in other window: ", fname, NFILEN, - EFNEW | EFCR | EFFILE | EFDEF)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - adjf = adjustname(fname, TRUE); - if (adjf == NULL) - return (FALSE); - if ((bp = findbuffer(adjf)) == NULL) - return (FALSE); - if (bp == curbp) - return (splitwind(f, n)); - if ((wp = popbuf(bp, WNONE)) == NULL) - return (FALSE); - curbp = bp; - curwp = wp; - if (bp->b_fname[0] == '\0') { - if ((status = readin(adjf)) != TRUE) - killbuffer(bp); - return (status); - } - return (TRUE); -} - -/* - * Given a file name, either find the buffer it uses, or create a new - * empty buffer to put it in. - */ -struct buffer * -findbuffer(char *fn) -{ - struct buffer *bp; - char bname[NBUFN], fname[NBUFN]; - - if (strlcpy(fname, fn, sizeof(fname)) >= sizeof(fname)) { - ewprintf("filename too long"); - return (NULL); - } - - for (bp = bheadp; bp != NULL; bp = bp->b_bufp) { - if (strcmp(bp->b_fname, fname) == 0) - return (bp); - } - /* Not found. Create a new one, adjusting name first */ - if (augbname(bname, fname, sizeof(bname)) == FALSE) - return (NULL); - - bp = bfind(bname, TRUE); - return (bp); -} - -/* - * Read the file "fname" into the current buffer. Make all of the text - * in the buffer go away, after checking for unsaved changes. This is - * called by the "read" command, the "visit" command, and the mainline - * (for "mg file"). - */ -int -readin(char *fname) -{ - struct mgwin *wp; - int status, i, ro = FALSE; - PF *ael; - - /* might be old */ - if (bclear(curbp) != TRUE) - return (TRUE); - /* Clear readonly. May be set by autoexec path */ - curbp->b_flag &= ~BFREADONLY; - if ((status = insertfile(fname, fname, TRUE)) != TRUE) { - ewprintf("File is not readable: %s", fname); - return (FALSE); - } - - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_bufp == curbp) { - wp->w_dotp = wp->w_linep = bfirstlp(curbp); - wp->w_doto = 0; - wp->w_markp = NULL; - wp->w_marko = 0; - } - } - - /* - * Call auto-executing function if we need to. - */ - if ((ael = find_autoexec(fname)) != NULL) { - for (i = 0; ael[i] != NULL; i++) - (*ael[i])(0, 1); - free(ael); - } - - /* no change */ - curbp->b_flag &= ~BFCHG; - - /* - * We need to set the READONLY flag after we insert the file, - * unless the file is a directory. - */ - if (access(fname, W_OK) && errno != ENOENT) - ro = TRUE; - if (fisdir(fname) == TRUE) - ro = TRUE; - if (ro == TRUE) - curbp->b_flag |= BFREADONLY; - - if (startrow) { - gotoline(FFARG, startrow); - startrow = 0; - } - - undo_add_modified(); - return (status); -} - -/* - * NB, getting file attributes is done here under control of a flag - * rather than in readin, which would be cleaner. I was concerned - * that some operating system might require the file to be open - * in order to get the information. Similarly for writing. - */ - -/* - * Insert a file in the current buffer, after dot. If file is a directory, - * and 'replacebuf' is TRUE, invoke dired mode, else die with an error. - * If file is a regular file, set mark at the end of the text inserted; - * point at the beginning. Return a standard status. Print a summary - * (lines read, error message) out as well. This routine also does the - * read end of backup processing. The BFBAK flag, if set in a buffer, - * says that a backup should be taken. It is set when a file is read in, - * but not on a new file. You don't need to make a backup copy of nothing. - */ - -static char *line = NULL; -static int linesize = 0; - -int -insertfile(char *fname, char *newname, int replacebuf) -{ - struct buffer *bp; - struct line *lp1, *lp2; - struct line *olp; /* line we started at */ - struct mgwin *wp; - int nbytes, s, nline = 0, siz, x, x2; - int opos; /* offset we started at */ - int oline; /* original line number */ - FILE *ffp; - - if (replacebuf == TRUE) - x = undo_enable(FFRAND, 0); - else - x = undo_enabled(); - - lp1 = NULL; - if (line == NULL) { - line = malloc(NLINE); - if (line == NULL) - panic("out of memory"); - linesize = NLINE; - } - - /* cheap */ - bp = curbp; - if (newname != NULL) { - (void)strlcpy(bp->b_fname, newname, sizeof(bp->b_fname)); - (void)xdirname(bp->b_cwd, newname, sizeof(bp->b_cwd)); - (void)strlcat(bp->b_cwd, "/", sizeof(bp->b_cwd)); - } - - /* hard file open */ - if ((s = ffropen(&ffp, fname, (replacebuf == TRUE) ? bp : NULL)) - == FIOERR) - goto out; - if (s == FIOFNF) { - /* file not found */ - if (newname != NULL) - ewprintf("(New file)"); - else - ewprintf("(File not found)"); - goto out; - } else if (s == FIODIR) { - /* file was a directory */ - if (replacebuf == FALSE) { - ewprintf("Cannot insert: file is a directory, %s", - fname); - goto cleanup; - } - killbuffer(bp); - bp = dired_(fname); - undo_enable(FFRAND, x); - if (bp == NULL) - return (FALSE); - curbp = bp; - return (showbuffer(bp, curwp, WFFULL | WFMODE)); - } else { - (void)xdirname(bp->b_cwd, fname, sizeof(bp->b_cwd)); - (void)strlcat(bp->b_cwd, "/", sizeof(bp->b_cwd)); - } - opos = curwp->w_doto; - oline = curwp->w_dotline; - /* - * Open a new line at dot and start inserting after it. - * We will delete this newline after insertion. - * Disable undo, as we create the undo record manually. - */ - x2 = undo_enable(FFRAND, 0); - (void)lnewline(); - olp = lback(curwp->w_dotp); - undo_enable(FFRAND, x2); - - nline = 0; - siz = 0; - while ((s = ffgetline(ffp, line, linesize, &nbytes)) != FIOERR) { -retry: - siz += nbytes + 1; - switch (s) { - case FIOSUC: - /* FALLTHRU */ - case FIOEOF: - ++nline; - if ((lp1 = lalloc(nbytes)) == NULL) { - /* keep message on the display */ - s = FIOERR; - undo_add_insert(olp, opos, - siz - nbytes - 1 - 1); - goto endoffile; - } - bcopy(line, <ext(lp1)[0], nbytes); - lp2 = lback(curwp->w_dotp); - lp2->l_fp = lp1; - lp1->l_fp = curwp->w_dotp; - lp1->l_bp = lp2; - curwp->w_dotp->l_bp = lp1; - if (s == FIOEOF) { - undo_add_insert(olp, opos, siz - 1); - goto endoffile; - } - break; - case FIOLONG: { - /* a line too long to fit in our buffer */ - char *cp; - int newsize; - - newsize = linesize * 2; - if (newsize < 0 || - (cp = malloc(newsize)) == NULL) { - ewprintf("Could not allocate %d bytes", - newsize); - s = FIOERR; - goto endoffile; - } - bcopy(line, cp, linesize); - free(line); - line = cp; - s = ffgetline(ffp, line + linesize, linesize, - &nbytes); - nbytes += linesize; - linesize = newsize; - if (s == FIOERR) - goto endoffile; - goto retry; - } - default: - ewprintf("Unknown code %d reading file", s); - s = FIOERR; - break; - } - } -endoffile: - /* ignore errors */ - (void)ffclose(ffp, NULL); - /* don't zap an error */ - if (s == FIOEOF) { - if (nline == 1) - ewprintf("(Read 1 line)"); - else - ewprintf("(Read %d lines)", nline); - } - /* set mark at the end of the text */ - curwp->w_dotp = curwp->w_markp = lback(curwp->w_dotp); - curwp->w_marko = llength(curwp->w_markp); - curwp->w_markline = oline + nline + 1; - /* - * if we are at the end of the file, ldelnewline is a no-op, - * but we still need to decrement the line and markline counts - * as we've accounted for this fencepost in our arithmetic - */ - if (lforw(curwp->w_dotp) == curwp->w_bufp->b_headp) { - curwp->w_bufp->b_lines--; - curwp->w_markline--; - } else - (void)ldelnewline(); - curwp->w_dotp = olp; - curwp->w_doto = opos; - curwp->w_dotline = oline; - if (olp == curbp->b_headp) - curwp->w_dotp = lforw(olp); - if (newname != NULL) - bp->b_flag |= BFCHG | BFBAK; /* Need a backup. */ - else - bp->b_flag |= BFCHG; - /* - * If the insert was at the end of buffer, set lp1 to the end of - * buffer line, and lp2 to the beginning of the newly inserted text. - * (Otherwise lp2 is set to NULL.) This is used below to set - * pointers in other windows correctly if they are also at the end of - * buffer. - */ - lp1 = bp->b_headp; - if (curwp->w_markp == lp1) { - lp2 = curwp->w_dotp; - } else { - /* delete extraneous newline */ - (void)ldelnewline(); -out: lp2 = NULL; - } - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_bufp == curbp) { - wp->w_rflag |= WFMODE | WFEDIT; - if (wp != curwp && lp2 != NULL) { - if (wp->w_dotp == lp1) - wp->w_dotp = lp2; - if (wp->w_markp == lp1) - wp->w_markp = lp2; - if (wp->w_linep == lp1) - wp->w_linep = lp2; - } - } - } - bp->b_lines += nline; -cleanup: - undo_enable(FFRAND, x); - - /* return FALSE if error */ - return (s != FIOERR); -} - -/* - * Ask for a file name and write the contents of the current buffer to that - * file. Update the remembered file name and clear the buffer changed flag. - * This handling of file names is different from the earlier versions and - * is more compatible with Gosling EMACS than with ITS EMACS. - */ -/* ARGSUSED */ -int -filewrite(int f, int n) -{ - struct stat statbuf; - int s; - char fname[NFILEN], bn[NBUFN], tmp[NFILEN + 25]; - char *adjfname, *bufp; - FILE *ffp; - - if (getbufcwd(fname, sizeof(fname)) != TRUE) - fname[0] = '\0'; - if ((bufp = eread("Write file: ", fname, NFILEN, - EFDEF | EFNEW | EFCR | EFFILE)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - - adjfname = adjustname(fname, TRUE); - if (adjfname == NULL) - return (FALSE); - - /* Check if file exists; write checks done later */ - if (stat(adjfname, &statbuf) == 0) { - snprintf(tmp, sizeof(tmp), "File `%s' exists; overwrite", - adjfname); - if ((s = eyorn(tmp)) != TRUE) - return (s); - } - - /* old attributes are no longer current */ - bzero(&curbp->b_fi, sizeof(curbp->b_fi)); - if ((s = writeout(&ffp, curbp, adjfname)) == TRUE) { - (void)strlcpy(curbp->b_fname, adjfname, sizeof(curbp->b_fname)); - if (getbufcwd(curbp->b_cwd, sizeof(curbp->b_cwd)) != TRUE) - (void)strlcpy(curbp->b_cwd, "/", sizeof(curbp->b_cwd)); - if (augbname(bn, curbp->b_fname, sizeof(bn)) - == FALSE) - return (FALSE); - free(curbp->b_bname); - if ((curbp->b_bname = strdup(bn)) == NULL) - return (FALSE); - (void)fupdstat(curbp); - curbp->b_flag &= ~(BFBAK | BFCHG); - upmodes(curbp); - } - return (s); -} - -/* - * Save the contents of the current buffer back into its associated file. - */ -#ifndef MAKEBACKUP -#define MAKEBACKUP TRUE -#endif /* !MAKEBACKUP */ -static int makebackup = MAKEBACKUP; - -/* ARGSUSED */ -int -filesave(int f, int n) -{ - if (curbp->b_fname[0] == '\0') - return (filewrite(f, n)); - else - return (buffsave(curbp)); -} - -/* - * Save the contents of the buffer argument into its associated file. Do - * nothing if there have been no changes (is this a bug, or a feature?). - * Error if there is no remembered file name. If this is the first write - * since the read or visit, then a backup copy of the file is made. - * Allow user to select whether or not to make backup files by looking at - * the value of makebackup. - */ -int -buffsave(struct buffer *bp) -{ - int s; - FILE *ffp; - - /* return, no changes */ - if ((bp->b_flag & BFCHG) == 0) { - ewprintf("(No changes need to be saved)"); - return (TRUE); - } - - /* must have a name */ - if (bp->b_fname[0] == '\0') { - ewprintf("No file name"); - return (FALSE); - } - - /* Ensure file has not been modified elsewhere */ - /* We don't use the ignore flag here */ - if (fchecktime(bp) != TRUE) { - if ((s = eyesno("File has changed on disk since last save. " - "Save anyway")) != TRUE) - return (s); - } - - if (makebackup && (bp->b_flag & BFBAK)) { - s = fbackupfile(bp->b_fname); - /* hard error */ - if (s == ABORT) - return (FALSE); - /* softer error */ - if (s == FALSE && - (s = eyesno("Backup error, save anyway")) != TRUE) - return (s); - } - if ((s = writeout(&ffp, bp, bp->b_fname)) == TRUE) { - (void)fupdstat(bp); - bp->b_flag &= ~(BFCHG | BFBAK); - upmodes(bp); - } - return (s); -} - -/* - * Since we don't have variables (we probably should) this is a command - * processor for changing the value of the make backup flag. If no argument - * is given, sets makebackup to true, so backups are made. If an argument is - * given, no backup files are made when saving a new version of a file. - */ -/* ARGSUSED */ -int -makebkfile(int f, int n) -{ - if (f & FFARG) - makebackup = n > 0; - else - makebackup = !makebackup; - ewprintf("Backup files %sabled", makebackup ? "en" : "dis"); - return (TRUE); -} - -/* - * NB: bp is passed to both ffwopen and ffclose because some - * attribute information may need to be updated at open time - * and others after the close. This is OS-dependent. Note - * that the ff routines are assumed to be able to tell whether - * the attribute information has been set up in this buffer - * or not. - */ - -/* - * This function performs the details of file writing; writing the file - * in buffer bp to file fn. Uses the file management routines in the - * "fileio.c" package. Most of the grief is checking of some sort. - * You may want to call fupdstat() after using this function. - */ -int -writeout(FILE ** ffp, struct buffer *bp, char *fn) -{ - int s; - - /* open writes message */ - if ((s = ffwopen(ffp, fn, bp)) != FIOSUC) - return (FALSE); - s = ffputbuf(*ffp, bp); - if (s == FIOSUC) { - /* no write error */ - s = ffclose(*ffp, bp); - if (s == FIOSUC) - ewprintf("Wrote %s", fn); - } else { - /* print a message indicating write error */ - (void)ffclose(*ffp, bp); - ewprintf("Unable to write %s", fn); - } - return (s == FIOSUC); -} - -/* - * Tag all windows for bp (all windows if bp == NULL) as needing their - * mode line updated. - */ -void -upmodes(struct buffer *bp) -{ - struct mgwin *wp; - - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) - if (bp == NULL || curwp->w_bufp == bp) - wp->w_rflag |= WFMODE; -} - -/* - * dirname using strlcpy semantic. - * Like dirname() except an empty string is returned in - * place of "/". This means we can always add a trailing - * slash and be correct. - * Address portability issues by copying argument - * before using. Some implementations modify the input string. - */ -size_t -xdirname(char *dp, const char *path, size_t dplen) -{ - char ts[NFILEN]; - size_t len; - - (void)strlcpy(ts, path, NFILEN); - len = strlcpy(dp, dirname(ts), dplen); - if (dplen > 0 && dp[0] == '/' && dp[1] == '\0') { - dp[0] = '\0'; - len = 0; - } - return (len); -} - -/* - * basename using strlcpy/strlcat semantic. - * Address portability issue by copying argument - * before using: some implementations modify the input string. - */ -size_t -xbasename(char *bp, const char *path, size_t bplen) -{ - char ts[NFILEN]; - - (void)strlcpy(ts, path, NFILEN); - return (strlcpy(bp, basename(ts), bplen)); -} diff --git a/mg/fileio.c b/mg/fileio.c deleted file mode 100644 index 0b63be8..0000000 --- a/mg/fileio.c +++ /dev/null @@ -1,754 +0,0 @@ -/* $OpenBSD: fileio.c,v 1.94 2012/07/10 06:28:12 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * POSIX fileio.c - */ -#include "def.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "kbd.h" -#include "pathnames.h" - -static char *bkuplocation(const char *); -static int bkupleavetmp(const char *); -char *expandtilde(const char *); - -static char *bkupdir; -static int leavetmp = 0; /* 1 = leave any '~' files in tmp dir */ - -/* - * Open a file for reading. - */ -int -ffropen(FILE ** ffp, const char *fn, struct buffer *bp) -{ - if ((*ffp = fopen(fn, "r")) == NULL) { - if (errno == ENOENT) - return (FIOFNF); - return (FIOERR); - } - - /* If 'fn' is a directory open it with dired. */ - if (fisdir(fn) == TRUE) - return (FIODIR); - - ffstat(*ffp, bp); - - return (FIOSUC); -} - -/* - * Update stat/dirty info - */ -void -ffstat(FILE *ffp, struct buffer *bp) -{ - struct stat sb; - - if (bp && fstat(fileno(ffp), &sb) == 0) { - /* set highorder bit to make sure this isn't all zero */ - bp->b_fi.fi_mode = sb.st_mode | 0x8000; - bp->b_fi.fi_uid = sb.st_uid; - bp->b_fi.fi_gid = sb.st_gid; - bp->b_fi.fi_mtime = sb.st_mtimespec; - /* Clear the ignore flag */ - bp->b_flag &= ~(BFIGNDIRTY | BFDIRTY); - } -} - -/* - * Update the status/dirty info. If there is an error, - * there's not a lot we can do. - */ -int -fupdstat(struct buffer *bp) -{ - FILE *ffp; - - if ((ffp = fopen(bp->b_fname, "r")) == NULL) { - if (errno == ENOENT) - return (FIOFNF); - return (FIOERR); - } - ffstat(ffp, bp); - (void)ffclose(ffp, bp); - return (FIOSUC); -} - -/* - * Open a file for writing. - */ -int -ffwopen(FILE ** ffp, const char *fn, struct buffer *bp) -{ - int fd; - mode_t fmode = DEFFILEMODE; - - if (bp && bp->b_fi.fi_mode) - fmode = bp->b_fi.fi_mode & 07777; - - fd = open(fn, O_RDWR | O_CREAT | O_TRUNC, fmode); - if (fd == -1) { - ffp = NULL; - ewprintf("Cannot open file for writing : %s", strerror(errno)); - return (FIOERR); - } - - if ((*ffp = fdopen(fd, "w")) == NULL) { - ewprintf("Cannot open file for writing : %s", strerror(errno)); - close(fd); - return (FIOERR); - } - - /* - * If we have file information, use it. We don't bother to check for - * errors, because there's no a lot we can do about it. Certainly - * trying to change ownership will fail if we aren't root. That's - * probably OK. If we don't have info, no need to get it, since any - * future writes will do the same thing. - */ - if (bp && bp->b_fi.fi_mode) { - fchmod(fd, bp->b_fi.fi_mode & 07777); - fchown(fd, bp->b_fi.fi_uid, bp->b_fi.fi_gid); - } - return (FIOSUC); -} - -/* - * Close a file. - */ -/* ARGSUSED */ -int -ffclose(FILE *ffp, struct buffer *bp) -{ - if (fclose(ffp) == 0) - return (FIOSUC); - return (FIOERR); -} - -/* - * Write a buffer to the already opened file. bp points to the - * buffer. Return the status. - */ -int -ffputbuf(FILE *ffp, struct buffer *bp) -{ - struct line *lp, *lpend; - - lpend = bp->b_headp; - for (lp = lforw(lpend); lp != lpend; lp = lforw(lp)) { - if (fwrite(ltext(lp), 1, llength(lp), ffp) != llength(lp)) { - ewprintf("Write I/O error"); - return (FIOERR); - } - if (lforw(lp) != lpend) /* no implied \n on last line */ - putc('\n', ffp); - } - /* - * XXX should be variable controlled (once we have variables) - */ - if (llength(lback(lpend)) != 0) { - if (eyorn("No newline at end of file, add one") == TRUE) { - lnewline_at(lback(lpend), llength(lback(lpend))); - putc('\n', ffp); - } - } - return (FIOSUC); -} - -/* - * Read a line from a file, and store the bytes - * in the supplied buffer. Stop on end of file or end of - * line. When FIOEOF is returned, there is a valid line - * of data without the normally implied \n. - * If the line length exceeds nbuf, FIOLONG is returned. - */ -int -ffgetline(FILE *ffp, char *buf, int nbuf, int *nbytes) -{ - int c, i; - - i = 0; - while ((c = getc(ffp)) != EOF && c != '\n') { - buf[i++] = c; - if (i >= nbuf) - return (FIOLONG); - } - if (c == EOF && ferror(ffp) != FALSE) { - ewprintf("File read error"); - return (FIOERR); - } - *nbytes = i; - return (c == EOF ? FIOEOF : FIOSUC); -} - -/* - * Make a backup copy of "fname". On Unix the backup has the same - * name as the original file, with a "~" on the end; this seems to - * be newest of the new-speak. The error handling is all in "file.c". - * We do a copy instead of a rename since otherwise another process - * with an open fd will get the backup, not the new file. This is - * a problem when using mg with things like crontab and vipw. - */ -int -fbackupfile(const char *fn) -{ - struct stat sb; - int from, to, serrno; - ssize_t nread; - char buf[BUFSIZ]; - char *nname, *tname, *bkpth; - - if (stat(fn, &sb) == -1) { - ewprintf("Can't stat %s : %s", fn, strerror(errno)); - return (FALSE); - } - - if ((bkpth = bkuplocation(fn)) == NULL) - return (FALSE); - - if (asprintf(&nname, "%s~", bkpth) == -1) { - ewprintf("Can't allocate backup file name : %s", strerror(errno)); - free(bkpth); - return (ABORT); - } - if (asprintf(&tname, "%s.XXXXXXXXXX", bkpth) == -1) { - ewprintf("Can't allocate temp file name : %s", strerror(errno)); - free(bkpth); - free(nname); - return (ABORT); - } - free(bkpth); - - if ((from = open(fn, O_RDONLY)) == -1) { - free(nname); - free(tname); - return (FALSE); - } - to = mkstemp(tname); - if (to == -1) { - serrno = errno; - close(from); - free(nname); - free(tname); - errno = serrno; - return (FALSE); - } - while ((nread = read(from, buf, sizeof(buf))) > 0) { - if (write(to, buf, (size_t)nread) != nread) { - nread = -1; - break; - } - } - serrno = errno; - (void) fchmod(to, (sb.st_mode & 0777)); - close(from); - close(to); - if (nread == -1) { - if (unlink(tname) == -1) - ewprintf("Can't unlink temp : %s", strerror(errno)); - } else { - if (rename(tname, nname) == -1) { - ewprintf("Can't rename temp : %s", strerror(errno)); - (void) unlink(tname); - nread = -1; - } - } - free(nname); - free(tname); - errno = serrno; - - return (nread == -1 ? FALSE : TRUE); -} - -/* - * Convert "fn" to a canonicalized absolute filename, replacing - * a leading ~/ with the user's home dir, following symlinks, and - * and remove all occurrences of /./ and /../ - */ -char * -adjustname(const char *fn, int slashslash) -{ - static char fnb[MAXPATHLEN]; - const char *cp, *ep = NULL; - char *path; - - if (slashslash == TRUE) { - cp = fn + strlen(fn) - 1; - for (; cp >= fn; cp--) { - if (ep && (*cp == '/')) { - fn = ep; - break; - } - if (*cp == '/' || *cp == '~') - ep = cp; - else - ep = NULL; - } - } - if ((path = expandtilde(fn)) == NULL) - return (NULL); - - if (realpath(path, fnb) == NULL) - (void)strlcpy(fnb, path, sizeof(fnb)); - - free(path); - return (fnb); -} - -/* - * Find a startup file for the user and return its name. As a service - * to other pieces of code that may want to find a startup file (like - * the terminal driver in particular), accepts a suffix to be appended - * to the startup file name. - */ -char * -startupfile(char *suffix) -{ - static char file[NFILEN]; - char *home; - int ret; - - if ((home = getenv("HOME")) == NULL || *home == '\0') - goto nohome; - - if (suffix == NULL) { - ret = snprintf(file, sizeof(file), _PATH_MG_STARTUP, home); - if (ret < 0 || ret >= sizeof(file)) - return (NULL); - } else { - ret = snprintf(file, sizeof(file), _PATH_MG_TERM, home, suffix); - if (ret < 0 || ret >= sizeof(file)) - return (NULL); - } - - if (access(file, R_OK) == 0) - return (file); -nohome: -#ifdef STARTUPFILE - if (suffix == NULL) { - ret = snprintf(file, sizeof(file), "%s", STARTUPFILE); - if (ret < 0 || ret >= sizeof(file)) - return (NULL); - } else { - ret = snprintf(file, sizeof(file), "%s%s", STARTUPFILE, - suffix); - if (ret < 0 || ret >= sizeof(file)) - return (NULL); - } - - if (access(file, R_OK) == 0) - return (file); -#endif /* STARTUPFILE */ - return (NULL); -} - -int -copy(char *frname, char *toname) -{ - int ifd, ofd; - char buf[BUFSIZ]; - mode_t fmode = DEFFILEMODE; /* XXX?? */ - struct stat orig; - ssize_t sr; - - if ((ifd = open(frname, O_RDONLY)) == -1) - return (FALSE); - if (fstat(ifd, &orig) == -1) { - ewprintf("fstat: %s", strerror(errno)); - close(ifd); - return (FALSE); - } - - if ((ofd = open(toname, O_WRONLY|O_CREAT|O_TRUNC, fmode)) == -1) { - close(ifd); - return (FALSE); - } - while ((sr = read(ifd, buf, sizeof(buf))) > 0) { - if (write(ofd, buf, (size_t)sr) != sr) { - ewprintf("write error : %s", strerror(errno)); - break; - } - } - if (fchmod(ofd, orig.st_mode) == -1) - ewprintf("Cannot set original mode : %s", strerror(errno)); - - if (sr == -1) { - ewprintf("Read error : %s", strerror(errno)); - close(ifd); - close(ofd); - return (FALSE); - } - /* - * It is "normal" for this to fail since we can't guarantee that - * we will be running as root. - */ - if (fchown(ofd, orig.st_uid, orig.st_gid) && errno != EPERM) - ewprintf("Cannot set owner : %s", strerror(errno)); - - (void) close(ifd); - (void) close(ofd); - - return (TRUE); -} - -/* - * return list of file names that match the name in buf. - */ -struct list * -make_file_list(char *buf) -{ - char *dir, *file, *cp; - size_t len, preflen; - int ret; - DIR *dirp; - struct dirent *dent; - struct list *last, *current; - char fl_name[NFILEN + 2]; - char prefixx[NFILEN + 1]; - - /* - * We need three different strings: - - * dir - the name of the directory containing what the user typed. - * Must be a real unix file name, e.g. no ~user, etc.. - * Must not end in /. - * prefix - the portion of what the user typed that is before the - * names we are going to find in the directory. Must have a - * trailing / if the user typed it. - * names from the directory - We open dir, and return prefix - * concatenated with names. - */ - - /* first we get a directory name we can look up */ - /* - * Names ending in . are potentially odd, because adjustname will - * treat foo/bar/.. as a foo/, whereas we are - * interested in names starting with .. - */ - len = strlen(buf); - if (len && buf[len - 1] == '.') { - buf[len - 1] = 'x'; - dir = adjustname(buf, TRUE); - buf[len - 1] = '.'; - } else - dir = adjustname(buf, TRUE); - if (dir == NULL) - return (NULL); - /* - * If the user typed a trailing / or the empty string - * he wants us to use his file spec as a directory name. - */ - if (len && buf[len - 1] != '/') { - file = strrchr(dir, '/'); - if (file) { - *file = '\0'; - if (*dir == '\0') - dir = "/"; - } else - return (NULL); - } - /* Now we get the prefix of the name the user typed. */ - if (strlcpy(prefixx, buf, sizeof(prefixx)) >= sizeof(prefixx)) - return (NULL); - cp = strrchr(prefixx, '/'); - if (cp == NULL) - prefixx[0] = '\0'; - else - cp[1] = '\0'; - - preflen = strlen(prefixx); - /* cp is the tail of buf that really needs to be compared. */ - cp = buf + preflen; - len = strlen(cp); - - /* - * Now make sure that file names will fit in the buffers allocated. - * SV files are fairly short. For BSD, something more general would - * be required. - */ - if (preflen > NFILEN - MAXNAMLEN) - return (NULL); - - /* loop over the specified directory, making up the list of files */ - - /* - * Note that it is worth our time to filter out names that don't - * match, even though our caller is going to do so again, and to - * avoid doing the stat if completion is being done, because stat'ing - * every file in the directory is relatively expensive. - */ - - dirp = opendir(dir); - if (dirp == NULL) - return (NULL); - last = NULL; - - while ((dent = readdir(dirp)) != NULL) { - int isdir; - if (strncmp(cp, dent->d_name, len) != 0) - continue; - isdir = 0; - if (dent->d_type == DT_DIR) { - isdir = 1; - } else if (dent->d_type == DT_LNK || - dent->d_type == DT_UNKNOWN) { - struct stat statbuf; - char statname[NFILEN + 2]; - - statbuf.st_mode = 0; - ret = snprintf(statname, sizeof(statname), "%s/%s", - dir, dent->d_name); - if (ret < 0 || ret > sizeof(statname) - 1) - continue; - if (stat(statname, &statbuf) < 0) - continue; - if (S_ISDIR(statbuf.st_mode)) - isdir = 1; - } - - if ((current = malloc(sizeof(struct list))) == NULL) { - free_file_list(last); - closedir(dirp); - return (NULL); - } - ret = snprintf(fl_name, sizeof(fl_name), - "%s%s%s", prefixx, dent->d_name, isdir ? "/" : ""); - if (ret < 0 || ret >= sizeof(fl_name)) { - free(current); - continue; - } - current->l_next = last; - current->l_name = strdup(fl_name); - last = current; - } - closedir(dirp); - - return (last); -} - -/* - * Test if a supplied filename refers to a directory - * Returns ABORT on error, TRUE if directory. FALSE otherwise - */ -int -fisdir(const char *fname) -{ - struct stat statbuf; - - if (stat(fname, &statbuf) != 0) - return (ABORT); - - if (S_ISDIR(statbuf.st_mode)) - return (TRUE); - - return (FALSE); -} - -/* - * Check the mtime of the supplied filename. - * Return TRUE if last mtime matches, FALSE if not, - * If the stat fails, return TRUE and try the save anyway - */ -int -fchecktime(struct buffer *bp) -{ - struct stat sb; - - if (stat(bp->b_fname, &sb) == -1) - return (TRUE); - - if (bp->b_fi.fi_mtime.tv_sec != sb.st_mtimespec.tv_sec || - bp->b_fi.fi_mtime.tv_nsec != sb.st_mtimespec.tv_nsec) - return (FALSE); - - return (TRUE); - -} - -/* - * Location of backup file. This function creates the correct path. - */ -static char * -bkuplocation(const char *fn) -{ - struct stat sb; - char *ret; - - if (bkupdir != NULL && (stat(bkupdir, &sb) == 0) && - S_ISDIR(sb.st_mode) && !bkupleavetmp(fn)) { - char fname[NFILEN]; - const char *c; - int i = 0, len; - - c = fn; - len = strlen(bkupdir); - - while (*c != '\0') { - /* Make sure we don't go over combined: - * strlen(bkupdir + '/' + fname + '\0') - */ - if (i >= NFILEN - len - 1) - return (NULL); - if (*c == '/') { - fname[i] = '!'; - } else if (*c == '!') { - if (i >= NFILEN - len - 2) - return (NULL); - fname[i++] = '!'; - fname[i] = '!'; - } else - fname[i] = *c; - i++; - c++; - } - fname[i] = '\0'; - if (asprintf(&ret, "%s/%s", bkupdir, fname) == -1) - return (NULL); - - } else if ((ret = strndup(fn, NFILEN)) == NULL) - return (NULL); - - return (ret); -} - -int -backuptohomedir(int f, int n) -{ - const char *c = _PATH_MG_DIR; - char *p; - - if (bkupdir == NULL) { - p = adjustname(c, TRUE); - bkupdir = strndup(p, NFILEN); - if (bkupdir == NULL) - return(FALSE); - - if (mkdir(bkupdir, 0700) == -1 && errno != EEXIST) { - free(bkupdir); - bkupdir = NULL; - } - } else { - free(bkupdir); - bkupdir = NULL; - } - - return (TRUE); -} - -/* - * For applications that use mg as the editor and have a desire to keep - * '~' files in the TMPDIR, toggle the location: /tmp | ~/.mg.d - */ -int -toggleleavetmp(int f, int n) -{ - leavetmp = !leavetmp; - - return (TRUE); -} - -/* - * Returns TRUE if fn is located in the temp directory and we want to save - * those backups there. - */ -int -bkupleavetmp(const char *fn) -{ - char *tmpdir, *tmp = NULL; - - if (!leavetmp) - return(FALSE); - - if((tmpdir = getenv("TMPDIR")) != NULL && *tmpdir != '\0') { - tmp = strstr(fn, tmpdir); - if (tmp == fn) - return (TRUE); - - return (FALSE); - } - - tmp = strstr(fn, "/tmp"); - if (tmp == fn) - return (TRUE); - - return (FALSE); -} - -/* - * Expand file names beginning with '~' if appropriate: - * 1, if ./~fn exists, continue without expanding tilde. - * 2, else, if username 'fn' exists, expand tilde with home directory path. - * 3, otherwise, continue and create new buffer called ~fn. - */ -char * -expandtilde(const char *fn) -{ - struct passwd *pw; - struct stat statbuf; - const char *cp; - char user[LOGIN_NAME_MAX], path[NFILEN]; - char *un, *ret; - size_t ulen, plen; - - path[0] = '\0'; - - if (fn[0] != '~' || stat(fn, &statbuf) == 0) { - if ((ret = strndup(fn, NFILEN)) == NULL) - return (NULL); - return(ret); - } - cp = strchr(fn, '/'); - if (cp == NULL) - cp = fn + strlen(fn); /* point to the NUL byte */ - ulen = cp - &fn[1]; - if (ulen >= sizeof(user)) { - if ((ret = strndup(fn, NFILEN)) == NULL) - return (NULL); - return(ret); - } - if (ulen == 0) { /* ~/ or ~ */ - if ((un = getlogin()) != NULL) - (void)strlcpy(user, un, sizeof(user)); - else - user[0] = '\0'; - } else { /* ~user/ or ~user */ - memcpy(user, &fn[1], ulen); - user[ulen] = '\0'; - } - pw = getpwnam(user); - if (pw != NULL) { - plen = strlcpy(path, pw->pw_dir, sizeof(path)); - if (plen == 0 || path[plen - 1] != '/') { - if (strlcat(path, "/", sizeof(path)) >= sizeof(path)) { - ewprintf("Path too long"); - return (NULL); - } - } - fn = cp; - if (*fn == '/') - fn++; - } - if (strlcat(path, fn, sizeof(path)) >= sizeof(path)) { - ewprintf("Path too long"); - return (NULL); - } - if ((ret = strndup(path, NFILEN)) == NULL) - return (NULL); - - return (ret); -} diff --git a/mg/funmap.c b/mg/funmap.c deleted file mode 100644 index aac58ce..0000000 --- a/mg/funmap.c +++ /dev/null @@ -1,281 +0,0 @@ -/* $OpenBSD: funmap.c,v 1.40 2012/06/14 17:21:22 lum Exp $ */ - -/* This file is in the public domain */ - -#include "def.h" -#include "kbd.h" -#include "funmap.h" - -/* - * If the function is NULL, it must be listed with the - * same name in the map_table. - */ - -struct funmap { - PF fn_funct; - const char *fn_name; - struct funmap *fn_next; -}; - -static struct funmap *funs; - -static struct funmap functnames[] = { - {apropos_command, "apropos",}, - {auto_execute, "auto-execute", }, - {fillmode, "auto-fill-mode",}, - {indentmode, "auto-indent-mode",}, - {backtoindent, "back-to-indentation",}, - {backuptohomedir, "backup-to-home-directory",}, - {backchar, "backward-char",}, - {delbword, "backward-kill-word",}, - {gotobop, "backward-paragraph",}, - {backword, "backward-word",}, - {gotobob, "beginning-of-buffer",}, - {gotobol, "beginning-of-line",}, - {showmatch, "blink-and-insert",}, - {bsmap, "bsmap-mode",}, - {NULL, "c-x 4 prefix",}, - {NULL, "c-x prefix",}, - {executemacro, "call-last-kbd-macro",}, - {capword, "capitalize-word",}, - {changedir, "cd",}, - {clearmark, "clear-mark",}, - {copyregion, "copy-region-as-kill",}, -#ifdef REGEX - {cntmatchlines, "count-matches",}, - {cntnonmatchlines, "count-non-matches",}, -#endif /* REGEX */ - {redefine_key, "define-key",}, - {backdel, "delete-backward-char",}, - {deblank, "delete-blank-lines",}, - {forwdel, "delete-char",}, - {delwhite, "delete-horizontal-space",}, - {delleadwhite, "delete-leading-space",}, - {deltrailwhite, "delete-trailing-space",}, -#ifdef REGEX - {delmatchlines, "delete-matching-lines",}, - {delnonmatchlines, "delete-non-matching-lines",}, -#endif /* REGEX */ - {onlywind, "delete-other-windows",}, - {delwind, "delete-window",}, - {wallchart, "describe-bindings",}, - {desckey, "describe-key-briefly",}, - {digit_argument, "digit-argument",}, - {lowerregion, "downcase-region",}, - {lowerword, "downcase-word",}, - {showversion, "emacs-version",}, - {finishmacro, "end-kbd-macro",}, - {globalwdtoggle, "global-wd-mode",}, - {gotoeob, "end-of-buffer",}, - {gotoeol, "end-of-line",}, - {enlargewind, "enlarge-window",}, - {NULL, "esc prefix",}, - {evalbuffer, "eval-current-buffer",}, - {evalexpr, "eval-expression",}, - {swapmark, "exchange-point-and-mark",}, - {extend, "execute-extended-command",}, - {fillpara, "fill-paragraph",}, - {filevisit, "find-file",}, - {filevisitro, "find-file-read-only",}, - {filevisitalt, "find-alternate-file",}, - {poptofile, "find-file-other-window",}, - {forwchar, "forward-char",}, - {gotoeop, "forward-paragraph",}, - {forwword, "forward-word",}, - {bindtokey, "global-set-key",}, - {unbindtokey, "global-unset-key",}, - {gotoline, "goto-line",}, - {help_help, "help-help",}, - {insert, "insert",}, - {bufferinsert, "insert-buffer",}, - {fileinsert, "insert-file",}, - {fillword, "insert-with-wrap",}, - {backisearch, "isearch-backward",}, - {forwisearch, "isearch-forward",}, - {joinline, "join-line",}, - {justone, "just-one-space",}, - {ctrlg, "keyboard-quit",}, - {killbuffer_cmd, "kill-buffer",}, - {killline, "kill-line",}, - {killpara, "kill-paragraph",}, - {killregion, "kill-region",}, - {delfword, "kill-word",}, - {toggleleavetmp, "leave-tmpdir-backups",}, - {linenotoggle, "line-number-mode",}, - {listbuffers, "list-buffers",}, - {evalfile, "load",}, - {localbind, "local-set-key",}, - {localunbind, "local-unset-key",}, - {makebkfile, "make-backup-files",}, - {markbuffer, "mark-whole-buffer",}, - {do_meta, "meta-key-mode",}, /* better name, anyone? */ - {negative_argument, "negative-argument",}, - {newline, "newline",}, - {lfindent, "newline-and-indent",}, - {indent, "indent-current-line",}, - {forwline, "next-line",}, -#ifdef NOTAB - {notabmode, "no-tab-mode",}, -#endif /* NOTAB */ - {notmodified, "not-modified",}, - {openline, "open-line",}, - {nextwind, "other-window",}, - {overwrite_mode, "overwrite-mode",}, - {prefixregion, "prefix-region",}, - {backline, "previous-line",}, - {prevwind, "previous-window",}, - {poptag, "pop-tag-mark",}, - {spawncli, "push-shell",}, - {findtag, "find-tag",}, - {tagsvisit, "visit-tags-table",}, - {showcwdir, "pwd",}, - {queryrepl, "query-replace",}, -#ifdef REGEX - {replstr, "replace-string",}, - {re_queryrepl, "query-replace-regexp",}, -#endif /* REGEX */ - {quote, "quoted-insert",}, -#ifdef REGEX - {re_searchagain, "re-search-again",}, - {re_backsearch, "re-search-backward",}, - {re_forwsearch, "re-search-forward",}, -#endif /* REGEX */ - {reposition, "recenter",}, - {redraw, "redraw-display",}, - {filesave, "save-buffer",}, - {quit, "save-buffers-kill-emacs",}, - {savebuffers, "save-some-buffers",}, - {backpage, "scroll-down",}, - {back1page, "scroll-one-line-down",}, - {forw1page, "scroll-one-line-up",}, - {pagenext, "scroll-other-window",}, - {forwpage, "scroll-up",}, - {searchagain, "search-again",}, - {backsearch, "search-backward",}, - {forwsearch, "search-forward",}, - {selfinsert, "self-insert-command",}, -#ifdef REGEX - {setcasefold, "set-case-fold-search",}, -#endif /* REGEX */ - {set_default_mode, "set-default-mode",}, - {setfillcol, "set-fill-column",}, - {setmark, "set-mark-command",}, - {setprefix, "set-prefix-string",}, - {piperegion, "shell-command-on-region",}, - {shrinkwind, "shrink-window",}, -#ifdef NOTAB - {space_to_tabstop, "space-to-tabstop",}, -#endif /* NOTAB */ - {splitwind, "split-window-vertically",}, - {definemacro, "start-kbd-macro",}, - {spawncli, "suspend-emacs",}, - {usebuffer, "switch-to-buffer",}, - {poptobuffer, "switch-to-buffer-other-window",}, - {togglereadonly, "toggle-read-only" }, - {twiddle, "transpose-chars",}, - {undo, "undo", }, - {undo_enable, "undo-enable", }, - {undo_boundary_enable, "undo-boundary-toggle", }, - {undo_add_boundary, "undo-boundary", }, - {undo_dump, "undo-list", }, - {universal_argument, "universal-argument",}, - {upperregion, "upcase-region",}, - {upperword, "upcase-word",}, - {showcpos, "what-cursor-position",}, - {filewrite, "write-file",}, - {yank, "yank",}, - {cssymbol, "cscope-find-this-symbol",}, - {csdefinition, "cscope-find-global-definition",}, - {csfuncalled, "cscope-find-called-functions",}, - {cscallerfuncs, "cscope-find-functions-calling-this-function",}, - {csfindtext, "cscope-find-this-text-string",}, - {csegrep, "cscope-find-egrep-pattern",}, - {csfindfile, "cscope-find-this-file",}, - {csfindinc, "cscope-find-files-including-file",}, - {csnextmatch, "cscope-next-symbol",}, - {csprevmatch, "cscope-prev-symbol",}, - {csnextfile, "cscope-next-file",}, - {csprevfile, "cscope-prev-file",}, - {cscreatelist, "cscope-create-list-of-files-to-index"}, - {NULL, NULL,} -}; - -void -funmap_init(void) -{ - struct funmap *fn; - - for (fn = functnames; fn->fn_name != NULL; fn++) { - fn->fn_next = funs; - funs = fn; - } -} - -int -funmap_add(PF fun, const char *fname) -{ - struct funmap *fn; - - if ((fn = malloc(sizeof(*fn))) == NULL) - return (FALSE); - - fn->fn_funct = fun; - fn->fn_name = fname; - fn->fn_next = funs; - - funs = fn; - return (TRUE); -} - -/* - * Translate from function name to function pointer. - */ -PF -name_function(const char *fname) -{ - struct funmap *fn; - - for (fn = funs; fn != NULL; fn = fn->fn_next) { - if (strcmp(fn->fn_name, fname) == 0) - return (fn->fn_funct); - } - return (NULL); -} - -const char * -function_name(PF fun) -{ - struct funmap *fn; - - for (fn = funs; fn != NULL; fn = fn->fn_next) { - if (fn->fn_funct == fun) - return (fn->fn_name); - } - return (NULL); -} - -/* - * List possible function name completions. - */ -struct list * -complete_function_list(const char *fname) -{ - struct funmap *fn; - struct list *head, *el; - int len; - - len = strlen(fname); - head = NULL; - for (fn = funs; fn != NULL; fn = fn->fn_next) { - if (memcmp(fname, fn->fn_name, len) == 0) { - if ((el = malloc(sizeof(*el))) == NULL) { - free_file_list(head); - return (NULL); - } - el->l_name = strdup(fn->fn_name); - el->l_next = head; - head = el; - } - } - return (head); -} diff --git a/mg/funmap.h b/mg/funmap.h deleted file mode 100644 index acc24ae..0000000 --- a/mg/funmap.h +++ /dev/null @@ -1,9 +0,0 @@ -/* $OpenBSD: funmap.h,v 1.7 2008/06/10 00:19:31 kjell Exp $ */ - -/* This file is in the public domain */ - -void funmap_init(void); -PF name_function(const char *); -const char *function_name(PF); -struct list *complete_function_list(const char *); -int funmap_add(PF, const char *); diff --git a/mg/grep.c b/mg/grep.c deleted file mode 100644 index 0d688b5..0000000 --- a/mg/grep.c +++ /dev/null @@ -1,365 +0,0 @@ -/* $OpenBSD: grep.c,v 1.38 2009/06/04 23:39:37 kjell Exp $ */ - -/* This file is in the public domain */ - -#include "def.h" -#include "kbd.h" -#include "funmap.h" - -#include -#include -#include -#include - -int globalwd = FALSE; -static int compile_goto_error(int, int); -int next_error(int, int); -static int grep(int, int); -static int gid(int, int); -static struct buffer *compile_mode(const char *, const char *); -static int xlint(int, int); -void grep_init(void); - -static char compile_last_command[NFILEN] = "make "; - -/* - * Hints for next-error - * - * XXX - need some kind of callback to find out when those get killed. - */ -struct mgwin *compile_win; -struct buffer *compile_buffer; - -static PF compile_pf[] = { - compile_goto_error -}; - -static struct KEYMAPE (1 + IMAPEXT) compilemap = { - 1, - 1 + IMAPEXT, - rescan, - { - { CCHR('M'), CCHR('M'), compile_pf, NULL } - } -}; - -void -grep_init(void) -{ - funmap_add(compile_goto_error, "compile-goto-error"); - funmap_add(next_error, "next-error"); - funmap_add(grep, "grep"); - funmap_add(xlint, "lint"); - funmap_add(compile, "compile"); - funmap_add(gid, "gid"); - maps_add((KEYMAP *)&compilemap, "compile"); -} - -/* ARGSUSED */ -static int -grep(int f, int n) -{ - char cprompt[NFILEN], *bufp; - struct buffer *bp; - struct mgwin *wp; - - (void)strlcpy(cprompt, "grep -n ", sizeof(cprompt)); - if ((bufp = eread("Run grep: ", cprompt, NFILEN, - EFDEF | EFNEW | EFCR)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - if (strlcat(cprompt, " /dev/null", sizeof(cprompt)) >= sizeof(cprompt)) - return (FALSE); - - if ((bp = compile_mode("*grep*", cprompt)) == NULL) - return (FALSE); - if ((wp = popbuf(bp, WNONE)) == NULL) - return (FALSE); - curbp = bp; - compile_win = curwp = wp; - return (TRUE); -} - -/* ARGSUSED */ -static int -xlint(int f, int n) -{ - char cprompt[NFILEN], *bufp; - struct buffer *bp; - struct mgwin *wp; - - (void)strlcpy(cprompt, "make lint ", sizeof(cprompt)); - if ((bufp = eread("Run lint: ", cprompt, NFILEN, - EFDEF | EFNEW | EFCR)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - - if ((bp = compile_mode("*lint*", cprompt)) == NULL) - return (FALSE); - if ((wp = popbuf(bp, WNONE)) == NULL) - return (FALSE); - curbp = bp; - compile_win = curwp = wp; - return (TRUE); -} - -/* ARGSUSED */ -int -compile(int f, int n) -{ - char cprompt[NFILEN], *bufp; - struct buffer *bp; - struct mgwin *wp; - - (void)strlcpy(cprompt, compile_last_command, sizeof(cprompt)); - if ((bufp = eread("Compile command: ", cprompt, NFILEN, - EFDEF | EFNEW | EFCR)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - if (savebuffers(f, n) == ABORT) - return (ABORT); - (void)strlcpy(compile_last_command, bufp, sizeof(compile_last_command)); - - if ((bp = compile_mode("*compile*", cprompt)) == NULL) - return (FALSE); - if ((wp = popbuf(bp, WNONE)) == NULL) - return (FALSE); - curbp = bp; - compile_win = curwp = wp; - gotoline(FFARG, 0); - return (TRUE); -} - -/* id-utils foo. */ -/* ARGSUSED */ -static int -gid(int f, int n) -{ - char command[NFILEN]; - char cprompt[NFILEN], c, *bufp; - struct buffer *bp; - struct mgwin *wp; - int i, j, len; - - /* catch ([^\s(){}]+)[\s(){}]* */ - - i = curwp->w_doto; - /* Skip backwards over delimiters we are currently on */ - while (i > 0) { - c = lgetc(curwp->w_dotp, i); - if (isalnum(c) || c == '_') - break; - - i--; - } - - /* Skip the symbol itself */ - for (; i > 0; i--) { - c = lgetc(curwp->w_dotp, i - 1); - if (!isalnum(c) && c != '_') - break; - } - /* Fill the symbol in cprompt[] */ - for (j = 0; j < sizeof(cprompt) - 1 && i < llength(curwp->w_dotp); - j++, i++) { - c = lgetc(curwp->w_dotp, i); - if (!isalnum(c) && c != '_') - break; - cprompt[j] = c; - } - cprompt[j] = '\0'; - - if ((bufp = eread("Run gid (with args): ", cprompt, NFILEN, - (j ? EFDEF : 0) | EFNEW | EFCR)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - len = snprintf(command, sizeof(command), "gid %s", cprompt); - if (len < 0 || len >= sizeof(command)) - return (FALSE); - - if ((bp = compile_mode("*gid*", command)) == NULL) - return (FALSE); - if ((wp = popbuf(bp, WNONE)) == NULL) - return (FALSE); - curbp = bp; - compile_win = curwp = wp; - return (TRUE); -} - -struct buffer * -compile_mode(const char *name, const char *command) -{ - struct buffer *bp; - FILE *fpipe; - char *buf; - size_t len; - int ret, n; - char cwd[NFILEN], qcmd[NFILEN]; - char timestr[NTIME]; - time_t t; - - n = snprintf(qcmd, sizeof(qcmd), "%s 2>&1", command); - if (n < 0 || n >= sizeof(qcmd)) - return (NULL); - - bp = bfind(name, TRUE); - if (bclear(bp) != TRUE) - return (NULL); - - if (getbufcwd(bp->b_cwd, sizeof(bp->b_cwd)) != TRUE) - return (NULL); - addlinef(bp, "cd %s", bp->b_cwd); - addline(bp, qcmd); - addline(bp, ""); - - if (getcwd(cwd, sizeof(cwd)) == NULL) - panic("Can't get current directory!"); - if (chdir(bp->b_cwd) == -1) { - ewprintf("Can't change dir to %s", bp->b_cwd); - return (NULL); - } - if ((fpipe = popen(qcmd, "r")) == NULL) { - ewprintf("Problem opening pipe"); - return (NULL); - } - /* - * We know that our commands are nice and the last line will end with - * a \n, so we don't need to try to deal with the last line problem - * in fgetln. - */ - while ((buf = fgetln(fpipe, &len)) != NULL) { - buf[len - 1] = '\0'; - addline(bp, buf); - } - ret = pclose(fpipe); - t = time(NULL); - strftime(timestr, sizeof(timestr), "%a %b %e %T %Y", localtime(&t)); - addline(bp, ""); - if (ret != 0) - addlinef(bp, "Command exited abnormally with code %d" - " at %s", ret, timestr); - else - addlinef(bp, "Command finished at %s", timestr); - - bp->b_dotp = bfirstlp(bp); - bp->b_modes[0] = name_mode("fundamental"); - bp->b_modes[1] = name_mode("compile"); - bp->b_nmodes = 1; - - compile_buffer = bp; - - if (chdir(cwd) == -1) { - ewprintf("Can't change dir back to %s", cwd); - return (NULL); - } - return (bp); -} - -/* ARGSUSED */ -static int -compile_goto_error(int f, int n) -{ - struct buffer *bp; - struct mgwin *wp; - char *fname, *line, *lp, *ln; - int lineno; - char *adjf, path[NFILEN]; - const char *errstr; - struct line *last; - - compile_win = curwp; - compile_buffer = curbp; - last = blastlp(compile_buffer); - - retry: - /* last line is compilation result */ - if (curwp->w_dotp == last) - return (FALSE); - - if ((line = linetostr(curwp->w_dotp)) == NULL) - return (FALSE); - lp = line; - if ((fname = strsep(&lp, ":")) == NULL || *fname == '\0') - goto fail; - if ((ln = strsep(&lp, ":")) == NULL || *ln == '\0') - goto fail; - lineno = (int)strtonum(ln, INT_MIN, INT_MAX, &errstr); - if (errstr) - goto fail; - - if (fname && fname[0] != '/') { - if (getbufcwd(path, sizeof(path)) == FALSE) - goto fail; - if (strlcat(path, fname, sizeof(path)) >= sizeof(path)) - goto fail; - adjf = path; - } else { - adjf = adjustname(fname, TRUE); - } - free(line); - - if (adjf == NULL) - return (FALSE); - - if ((bp = findbuffer(adjf)) == NULL) - return (FALSE); - if ((wp = popbuf(bp, WNONE)) == NULL) - return (FALSE); - curbp = bp; - curwp = wp; - if (bp->b_fname[0] == '\0') - readin(adjf); - gotoline(FFARG, lineno); - return (TRUE); -fail: - free(line); - if (curwp->w_dotp != blastlp(curbp)) { - curwp->w_dotp = lforw(curwp->w_dotp); - curwp->w_rflag |= WFMOVE; - goto retry; - } - ewprintf("No more hits"); - return (FALSE); -} - -/* ARGSUSED */ -int -next_error(int f, int n) -{ - if (compile_win == NULL || compile_buffer == NULL) { - ewprintf("No compilation active"); - return (FALSE); - } - curwp = compile_win; - curbp = compile_buffer; - if (curwp->w_dotp == blastlp(curbp)) { - ewprintf("No more hits"); - return (FALSE); - } - curwp->w_dotp = lforw(curwp->w_dotp); - curwp->w_rflag |= WFMOVE; - - return (compile_goto_error(f, n)); -} - -/* - * Since we don't have variables (we probably should) these are command - * processors for changing the values of mode flags. - */ -/* ARGSUSED */ -int -globalwdtoggle(int f, int n) -{ - if (f & FFARG) - globalwd = n > 0; - else - globalwd = !globalwd; - - sgarbf = TRUE; - - return (TRUE); -} diff --git a/mg/help.c b/mg/help.c deleted file mode 100644 index 938f813..0000000 --- a/mg/help.c +++ /dev/null @@ -1,231 +0,0 @@ -/* $OpenBSD: help.c,v 1.34 2012/04/12 04:47:59 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Help functions for Mg 2 - */ - -#include "def.h" -#include "funmap.h" - -#include "kbd.h" -#include "key.h" -#include "macro.h" - -static int showall(struct buffer *, KEYMAP *, char *); -static int findbind(KEYMAP *, PF, char *, size_t); - -/* - * Read a key from the keyboard, and look it up in the keymap. - * Display the name of the function currently bound to the key. - */ -/* ARGSUSED */ -int -desckey(int f, int n) -{ - KEYMAP *curmap; - PF funct; - int c, m, i, num; - char *pep; - char dprompt[80]; - - if (inmacro) - return (TRUE); /* ignore inside keyboard macro */ - - num = strlcpy(dprompt, "Describe key briefly: ", sizeof(dprompt)); - if (num >= sizeof(dprompt)) - num = sizeof(dprompt) - 1; - pep = dprompt + num; - key.k_count = 0; - m = curbp->b_nmodes; - curmap = curbp->b_modes[m]->p_map; - for (;;) { - for (;;) { - ewprintf("%s", dprompt); - pep[-1] = ' '; - pep = getkeyname(pep, sizeof(dprompt) - (pep - dprompt), - key.k_chars[key.k_count++] = c = getkey(FALSE)); - if ((funct = doscan(curmap, c, &curmap)) != NULL) - break; - *pep++ = '-'; - *pep = '\0'; - } - if (funct != rescan) - break; - if (ISUPPER(key.k_chars[key.k_count - 1])) { - funct = doscan(curmap, - TOLOWER(key.k_chars[key.k_count - 1]), &curmap); - if (funct == NULL) { - *pep++ = '-'; - *pep = '\0'; - continue; - } - if (funct != rescan) - break; - } -nextmode: - if (--m < 0) - break; - curmap = curbp->b_modes[m]->p_map; - for (i = 0; i < key.k_count; i++) { - funct = doscan(curmap, key.k_chars[i], &curmap); - if (funct != NULL) { - if (i == key.k_count - 1 && funct != rescan) - goto found; - funct = rescan; - goto nextmode; - } - } - *pep++ = '-'; - *pep = '\0'; - } -found: - if (funct == rescan || funct == selfinsert) - ewprintf("%k is not bound to any function"); - else if ((pep = (char *)function_name(funct)) != NULL) - ewprintf("%k runs the command %s", pep); - else - ewprintf("%k is bound to an unnamed function"); - return (TRUE); -} - -/* - * This function creates a table, listing all of the command - * keys and their current bindings, and stores the table in the - * *help* pop-up buffer. This lets Mg produce it's own wall chart. - */ -/* ARGSUSED */ -int -wallchart(int f, int n) -{ - int m; - struct buffer *bp; - - bp = bfind("*help*", TRUE); - if (bclear(bp) != TRUE) - /* clear it out */ - return (FALSE); - bp->b_flag |= BFREADONLY; - for (m = curbp->b_nmodes; m > 0; m--) { - if ((addlinef(bp, "Local keybindings for mode %s:", - curbp->b_modes[m]->p_name) == FALSE) || - (showall(bp, curbp->b_modes[m]->p_map, "") == FALSE) || - (addline(bp, "") == FALSE)) - return (FALSE); - } - if ((addline(bp, "Global bindings:") == FALSE) || - (showall(bp, fundamental_map, "") == FALSE)) - return (FALSE); - return (popbuftop(bp, WNONE)); -} - -static int -showall(struct buffer *bp, KEYMAP *map, char *prefix) -{ - KEYMAP *newmap; - char buf[80], keybuf[16]; - PF fun; - int c; - - if (addline(bp, "") == FALSE) - return (FALSE); - - /* XXX - 256 ? */ - for (c = 0; c < 256; c++) { - fun = doscan(map, c, &newmap); - if (fun == rescan || fun == selfinsert) - continue; - getkeyname(buf, sizeof(buf), c); - (void)snprintf(keybuf, sizeof(keybuf), "%s%s ", prefix, buf); - if (fun == NULL) { - if (showall(bp, newmap, keybuf) == FALSE) - return (FALSE); - } else { - if (addlinef(bp, "%-16s%s", keybuf, - function_name(fun)) == FALSE) - return (FALSE); - } - } - return (TRUE); -} - -int -help_help(int f, int n) -{ - KEYMAP *kp; - PF funct; - - if ((kp = name_map("help")) == NULL) - return (FALSE); - ewprintf("a b c: "); - do { - funct = doscan(kp, getkey(FALSE), NULL); - } while (funct == NULL || funct == help_help); - - if (macrodef && macrocount < MAXMACRO) - macro[macrocount - 1].m_funct = funct; - - return ((*funct)(f, n)); -} - -/* ARGSUSED */ -int -apropos_command(int f, int n) -{ - struct buffer *bp; - struct list *fnames, *el; - char string[32]; - - if (eread("apropos: ", string, sizeof(string), EFNUL | EFNEW) == NULL) - return (ABORT); - /* FALSE means we got a 0 character string, which is fine */ - bp = bfind("*help*", TRUE); - if (bclear(bp) == FALSE) - return (FALSE); - - fnames = complete_function_list(""); - for (el = fnames; el != NULL; el = el->l_next) { - char buf[32]; - - if (strstr(el->l_name, string) == NULL) - continue; - - buf[0] = '\0'; - findbind(fundamental_map, name_function(el->l_name), - buf, sizeof(buf)); - - if (addlinef(bp, "%-32s%s", el->l_name, buf) == FALSE) { - free_file_list(fnames); - return (FALSE); - } - } - free_file_list(fnames); - return (popbuftop(bp, WNONE)); -} - -static int -findbind(KEYMAP *map, PF fun, char *buf, size_t len) -{ - KEYMAP *newmap; - PF nfun; - char buf2[16], keybuf[16]; - int c; - - /* XXX - 256 ? */ - for (c = 0; c < 256; c++) { - nfun = doscan(map, c, &newmap); - if (nfun == fun) { - getkeyname(buf, len, c); - return (TRUE); - } - if (nfun == NULL) { - if (findbind(newmap, fun, buf2, sizeof(buf2)) == TRUE) { - getkeyname(keybuf, sizeof(keybuf), c); - (void)snprintf(buf, len, "%s %s", keybuf, buf2); - return (TRUE); - } - } - } - return (FALSE); -} diff --git a/mg/kbd.c b/mg/kbd.c deleted file mode 100644 index 0eb3c36..0000000 --- a/mg/kbd.c +++ /dev/null @@ -1,436 +0,0 @@ -/* $OpenBSD: kbd.c,v 1.25 2012/04/12 04:47:59 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Terminal independent keyboard handling. - */ - -#include "def.h" -#include "kbd.h" -#include "key.h" -#include "macro.h" - -#ifndef METABIT -#define METABIT 0x80 -#endif /* !METABIT */ - -#ifndef NO_DPROMPT -#define PROMPTL 80 -char prompt[PROMPTL] = "", *promptp = prompt; -#endif /* !NO_DPROMPT */ - -static int mgwrap(PF, int, int); - -static int use_metakey = TRUE; -static int pushed = FALSE; -static int pushedc; - -struct map_element *ele; - -struct key key; - -/* - * Toggle the value of use_metakey - */ -int -do_meta(int f, int n) -{ - if (f & FFARG) - use_metakey = n > 0; - else - use_metakey = !use_metakey; - ewprintf("Meta keys %sabled", use_metakey ? "en" : "dis"); - return (TRUE); -} - -static int bs_map = 0; - -/* - * Toggle backspace mapping - */ -int -bsmap(int f, int n) -{ - if (f & FFARG) - bs_map = n > 0; - else - bs_map = !bs_map; - ewprintf("Backspace mapping %sabled", bs_map ? "en" : "dis"); - return (TRUE); -} - -void -ungetkey(int c) -{ - if (use_metakey && pushed && c == CCHR('[')) - pushedc |= METABIT; - else - pushedc = c; - pushed = TRUE; -} - -int -getkey(int flag) -{ - int c; - -#ifndef NO_DPROMPT - if (flag && !pushed) { - if (prompt[0] != '\0' && ttwait(2000)) { - /* avoid problems with % */ - ewprintf("%s", prompt); - /* put the cursor back */ - update(); - epresf = KCLEAR; - } - if (promptp > prompt) - *(promptp - 1) = ' '; - } -#endif /* !NO_DPROMPT */ - if (pushed) { - c = pushedc; - pushed = FALSE; - } else - c = ttgetc(); - - if (bs_map) { - if (c == CCHR('H')) - c = CCHR('?'); - else if (c == CCHR('?')) - c = CCHR('H'); - } - if (use_metakey && (c & METABIT)) { - pushedc = c & ~METABIT; - pushed = TRUE; - c = CCHR('['); - } -#ifndef NO_DPROMPT - if (flag && promptp < &prompt[PROMPTL - 5]) { - promptp = getkeyname(promptp, - sizeof(prompt) - (promptp - prompt) - 1, c); - *promptp++ = '-'; - *promptp = '\0'; - } -#endif /* !NO_DPROMPT */ - return (c); -} - -/* - * doscan scans a keymap for a keyboard character and returns a pointer - * to the function associated with that character. Sets ele to the - * keymap element the keyboard was found in as a side effect. - */ -PF -doscan(KEYMAP *map, int c, KEYMAP **newmap) -{ - struct map_element *elec = &map->map_element[0]; - struct map_element *last = &map->map_element[map->map_num]; - PF ret; - - while (elec < last && c > elec->k_num) - elec++; - - /* used by prefix and binding code */ - ele = elec; - if (elec >= last || c < elec->k_base) - ret = map->map_default; - else - ret = elec->k_funcp[c - elec->k_base]; - if (ret == NULL && newmap != NULL) - *newmap = elec->k_prefmap; - - return (ret); -} - -int -doin(void) -{ - KEYMAP *curmap; - PF funct; - -#ifndef NO_DPROMPT - *(promptp = prompt) = '\0'; -#endif /* !NO_DPROMPT */ - curmap = curbp->b_modes[curbp->b_nmodes]->p_map; - key.k_count = 0; - while ((funct = doscan(curmap, (key.k_chars[key.k_count++] = - getkey(TRUE)), &curmap)) == NULL) - /* nothing */; - - if (macrodef && macrocount < MAXMACRO) - macro[macrocount++].m_funct = funct; - - return (mgwrap(funct, 0, 1)); -} - -int -rescan(int f, int n) -{ - int c; - KEYMAP *curmap; - int i; - PF fp = NULL; - int md = curbp->b_nmodes; - - for (;;) { - if (ISUPPER(key.k_chars[key.k_count - 1])) { - c = TOLOWER(key.k_chars[key.k_count - 1]); - curmap = curbp->b_modes[md]->p_map; - for (i = 0; i < key.k_count - 1; i++) { - if ((fp = doscan(curmap, (key.k_chars[i]), - &curmap)) != NULL) - break; - } - if (fp == NULL) { - if ((fp = doscan(curmap, c, NULL)) == NULL) - while ((fp = doscan(curmap, - key.k_chars[key.k_count++] = - getkey(TRUE), &curmap)) == NULL) - /* nothing */; - if (fp != rescan) { - if (macrodef && macrocount <= MAXMACRO) - macro[macrocount - 1].m_funct - = fp; - return (mgwrap(fp, f, n)); - } - } - } - /* try previous mode */ - if (--md < 0) - return (ABORT); - curmap = curbp->b_modes[md]->p_map; - for (i = 0; i < key.k_count; i++) { - if ((fp = doscan(curmap, (key.k_chars[i]), &curmap)) != NULL) - break; - } - if (fp == NULL) { - while ((fp = doscan(curmap, key.k_chars[i++] = - getkey(TRUE), &curmap)) == NULL) - /* nothing */; - key.k_count = i; - } - if (fp != rescan && i >= key.k_count - 1) { - if (macrodef && macrocount <= MAXMACRO) - macro[macrocount - 1].m_funct = fp; - return (mgwrap(fp, f, n)); - } - } -} - -int -universal_argument(int f, int n) -{ - KEYMAP *curmap; - PF funct; - int c, nn = 4; - - if (f & FFUNIV) - nn *= n; - for (;;) { - key.k_chars[0] = c = getkey(TRUE); - key.k_count = 1; - if (c == '-') - return (negative_argument(f, nn)); - if (c >= '0' && c <= '9') - return (digit_argument(f, nn)); - curmap = curbp->b_modes[curbp->b_nmodes]->p_map; - while ((funct = doscan(curmap, c, &curmap)) == NULL) { - key.k_chars[key.k_count++] = c = getkey(TRUE); - } - if (funct != universal_argument) { - if (macrodef && macrocount < MAXMACRO - 1) { - if (f & FFARG) - macrocount--; - macro[macrocount++].m_count = nn; - macro[macrocount++].m_funct = funct; - } - return (mgwrap(funct, FFUNIV, nn)); - } - nn <<= 2; - } -} - -/* ARGSUSED */ -int -digit_argument(int f, int n) -{ - KEYMAP *curmap; - PF funct; - int nn, c; - - nn = key.k_chars[key.k_count - 1] - '0'; - for (;;) { - c = getkey(TRUE); - if (c < '0' || c > '9') - break; - nn *= 10; - nn += c - '0'; - } - key.k_chars[0] = c; - key.k_count = 1; - curmap = curbp->b_modes[curbp->b_nmodes]->p_map; - while ((funct = doscan(curmap, c, &curmap)) == NULL) { - key.k_chars[key.k_count++] = c = getkey(TRUE); - } - if (macrodef && macrocount < MAXMACRO - 1) { - if (f & FFARG) - macrocount--; - else - macro[macrocount - 1].m_funct = universal_argument; - macro[macrocount++].m_count = nn; - macro[macrocount++].m_funct = funct; - } - return (mgwrap(funct, FFOTHARG, nn)); -} - -int -negative_argument(int f, int n) -{ - KEYMAP *curmap; - PF funct; - int c; - int nn = 0; - - for (;;) { - c = getkey(TRUE); - if (c < '0' || c > '9') - break; - nn *= 10; - nn += c - '0'; - } - if (nn) - nn = -nn; - else - nn = -n; - key.k_chars[0] = c; - key.k_count = 1; - curmap = curbp->b_modes[curbp->b_nmodes]->p_map; - while ((funct = doscan(curmap, c, &curmap)) == NULL) { - key.k_chars[key.k_count++] = c = getkey(TRUE); - } - if (macrodef && macrocount < MAXMACRO - 1) { - if (f & FFARG) - macrocount--; - else - macro[macrocount - 1].m_funct = universal_argument; - macro[macrocount++].m_count = nn; - macro[macrocount++].m_funct = funct; - } - return (mgwrap(funct, FFNEGARG, nn)); -} - -/* - * Insert a character. While defining a macro, create a "LINE" containing - * all inserted characters. - */ -int -selfinsert(int f, int n) -{ - struct line *lp; - int c; - int count; - - if (n < 0) - return (FALSE); - if (n == 0) - return (TRUE); - c = key.k_chars[key.k_count - 1]; - - if (macrodef && macrocount < MAXMACRO) { - if (f & FFARG) - macrocount -= 2; - - /* last command was insert -- tack on the end */ - if (lastflag & CFINS) { - macrocount--; - /* Ensure the line can handle the new characters */ - if (maclcur->l_size < maclcur->l_used + n) { - if (lrealloc(maclcur, maclcur->l_used + n) == - FALSE) - return (FALSE); - } - maclcur->l_used += n; - /* Copy in the new data */ - for (count = maclcur->l_used - n; - count < maclcur->l_used; count++) - maclcur->l_text[count] = c; - } else { - macro[macrocount - 1].m_funct = insert; - if ((lp = lalloc(n)) == NULL) - return (FALSE); - lp->l_bp = maclcur; - lp->l_fp = maclcur->l_fp; - maclcur->l_fp = lp; - maclcur = lp; - for (count = 0; count < n; count++) - lp->l_text[count] = c; - } - thisflag |= CFINS; - } - if (c == '\n') { - do { - count = lnewline(); - } while (--n && count == TRUE); - return (count); - } - - /* overwrite mode */ - if (curbp->b_flag & BFOVERWRITE) { - lchange(WFEDIT); - while (curwp->w_doto < llength(curwp->w_dotp) && n--) - lputc(curwp->w_dotp, curwp->w_doto++, c); - if (n <= 0) - return (TRUE); - } - return (linsert(n, c)); -} - -/* - * This could be implemented as a keymap with everything defined as self-insert. - */ -int -quote(int f, int n) -{ - int c; - - key.k_count = 1; - if ((key.k_chars[0] = getkey(TRUE)) >= '0' && key.k_chars[0] <= '7') { - key.k_chars[0] -= '0'; - if ((c = getkey(TRUE)) >= '0' && c <= '7') { - key.k_chars[0] <<= 3; - key.k_chars[0] += c - '0'; - if ((c = getkey(TRUE)) >= '0' && c <= '7') { - key.k_chars[0] <<= 3; - key.k_chars[0] += c - '0'; - } else - ungetkey(c); - } else - ungetkey(c); - } - return (selfinsert(f, n)); -} - -/* - * Wraper function to count invocation repeats. - * We ignore any function whose sole purpose is to get us - * to the intended function. - */ -static int -mgwrap(PF funct, int f, int n) -{ - static PF ofp; - - if (funct != rescan && - funct != negative_argument && - funct != digit_argument && - funct != universal_argument) { - if (funct == ofp) - rptcount++; - else - rptcount = 0; - ofp = funct; - } - - return ((*funct)(f, n)); -} diff --git a/mg/kbd.h b/mg/kbd.h deleted file mode 100644 index 67b244c..0000000 --- a/mg/kbd.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $OpenBSD: kbd.h,v 1.18 2006/07/27 19:59:29 deraadt Exp $ */ - -/* This file is in the public domain. */ - -/* - * kbd.h: type definitions for symbol.c and kbd.c for mg experimental - */ - -struct map_element { - KCHAR k_base; /* first key in element */ - KCHAR k_num; /* last key in element */ - PF *k_funcp; /* pointer to array of pointers */ - /* to functions */ - struct keymap_s *k_prefmap; /* keymap of ONLY prefix key in */ - /* element */ -}; - -/* - * Predefined keymaps are NOT type KEYMAP because final array needs - * dimension. If any changes are made to this struct, they must be reflected - * in all keymap declarations. - */ - -#define KEYMAPE(NUM) { \ - short map_num; /* elements used */ \ - short map_max; /* elements allocated */\ - PF map_default; /* default function */ \ - struct map_element map_element[NUM]; /* really [e_max] */ \ -} -typedef struct keymap_s KEYMAPE(1) KEYMAP; - -/* Number of map_elements to grow an overflowed keymap by */ -#define IMAPEXT 0 -#define MAPGROW 3 -#define MAPINIT (MAPGROW+1) - -/* Max number of default bindings added to avoid creating new element */ -#define MAPELEDEF 4 - -struct maps_s { - KEYMAP *p_map; - const char *p_name; - struct maps_s *p_next; -}; - -extern struct maps_s *maps; -extern struct maps_s fundamental_mode; -#define fundamental_map (fundamental_mode.p_map) - -int dobindkey(KEYMAP *, const char *, const char *); -KEYMAP *name_map(const char *); -struct maps_s *name_mode(const char *); -PF doscan(KEYMAP *, int, KEYMAP **); -void maps_init(void); -int maps_add(KEYMAP *, const char *); - -extern struct map_element *ele; -extern struct maps_s *defb_modes[]; diff --git a/mg/key.h b/mg/key.h deleted file mode 100644 index 3b2a7cf..0000000 --- a/mg/key.h +++ /dev/null @@ -1,14 +0,0 @@ -/* $OpenBSD: key.h,v 1.5 2005/06/14 18:14:40 kjell Exp $ */ - -/* This file is in the public domain. */ - -/* key.h: Insert file for mg 2 functions that need to reference key pressed */ - -#define MAXKEY 8 /* maximum number of prefix chars */ - -struct key { /* the chacter sequence in a key */ - int k_count; /* number of chars */ - KCHAR k_chars[MAXKEY]; /* chars */ -}; - -extern struct key key; diff --git a/mg/keymap.c b/mg/keymap.c deleted file mode 100644 index 94aead6..0000000 --- a/mg/keymap.c +++ /dev/null @@ -1,567 +0,0 @@ -/* $OpenBSD: keymap.c,v 1.50 2012/06/07 15:15:04 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Keyboard maps. This is character set dependent. The terminal specific - * parts of building the keymap has been moved to a better place. - */ - -#include "def.h" -#include "kbd.h" - -/* - * initial keymap declarations, deepest first - */ - -static PF cHcG[] = { - ctrlg, /* ^G */ - help_help /* ^H */ -}; - -static PF cHa[] = { - apropos_command, /* a */ - wallchart, /* b */ - desckey /* c */ -}; - -struct KEYMAPE (2 + IMAPEXT) helpmap = { - 2, - 2 + IMAPEXT, - rescan, - { - { - CCHR('G'), CCHR('H'), cHcG, NULL - }, - { - 'a', 'c', cHa, NULL - } - } -}; - -static PF cCsc[] = { - cscallerfuncs, /* c */ - csdefinition, /* d */ - csegrep, /* e */ - csfindfile, /* f */ - rescan, /* g */ - rescan, /* h */ - csfindinc, /* i */ - rescan, /* j */ - rescan, /* k */ - rescan, /* l */ - rescan, /* m */ - csnextmatch, /* n */ - rescan, /* o */ - csprevmatch, /* p */ - rescan, /* q */ - rescan, /* r */ - cssymbol, /* s */ - csfindtext /* t */ -}; - -static struct KEYMAPE (1 + IMAPEXT) cCsmap = { - 1, - 1 + IMAPEXT, - rescan, - { - { - 'c', 't', cCsc, NULL - } - } -}; - -static PF cCs[] = { - NULL /* s */ -}; - -struct KEYMAPE (2 + IMAPEXT) ccmap = { - 2, - 2 + IMAPEXT, - rescan, - { - { - CCHR('@'), CCHR('@'), (PF[]){ rescan }, NULL - }, - { - 's', 's', cCs, (KEYMAP *) & cCsmap - } - } -}; - -static PF cX4cF[] = { - poptofile, /* ^f */ - ctrlg /* ^g */ -}; -static PF cX4b[] = { - poptobuffer, /* b */ - rescan, /* c */ - rescan, /* d */ - rescan, /* e */ - poptofile /* f */ -}; -static struct KEYMAPE (2 + IMAPEXT) cX4map = { - 2, - 2 + IMAPEXT, - rescan, - { - { - CCHR('F'), CCHR('G'), cX4cF, NULL - }, - { - 'b', 'f', cX4b, NULL - } - } -}; - -static PF cXcB[] = { - listbuffers, /* ^B */ - quit, /* ^C */ - rescan, /* ^D */ - rescan, /* ^E */ - filevisit, /* ^F */ - ctrlg /* ^G */ -}; - -static PF cXcL[] = { - lowerregion, /* ^L */ - rescan, /* ^M */ - rescan, /* ^N */ - deblank, /* ^O */ - rescan, /* ^P */ - togglereadonly, /* ^Q */ - filevisitro, /* ^R */ - filesave, /* ^S */ - rescan, /* ^T */ - upperregion, /* ^U */ - filevisitalt, /* ^V */ - filewrite, /* ^W */ - swapmark /* ^X */ -}; - -static PF cXlp[] = { - definemacro, /* ( */ - finishmacro /* ) */ -}; - -static PF cX0[] = { - delwind, /* 0 */ - onlywind, /* 1 */ - splitwind, /* 2 */ - rescan, /* 3 */ - NULL /* 4 */ -}; - -static PF cXeq[] = { - showcpos /* = */ -}; - -static PF cXcar[] = { - enlargewind, /* ^ */ - rescan, /* _ */ - next_error, /* ` */ - rescan, /* a */ - usebuffer, /* b */ - rescan, /* c */ - rescan, /* d */ - executemacro, /* e */ - setfillcol, /* f */ - gotoline, /* g */ - markbuffer, /* h */ - fileinsert, /* i */ - rescan, /* j */ - killbuffer_cmd, /* k */ - rescan, /* l */ - rescan, /* m */ - nextwind, /* n */ - nextwind, /* o */ - prevwind, /* p */ - rescan, /* q */ - rescan, /* r */ - savebuffers, /* s */ - rescan, /* t */ - undo /* u */ -}; - -struct KEYMAPE (6 + IMAPEXT) cXmap = { - 6, - 6 + IMAPEXT, - rescan, - { - { - CCHR('B'), CCHR('G'), cXcB, NULL - }, - { - CCHR('L'), CCHR('X'), cXcL, NULL - }, - { - '(', ')', cXlp, NULL - }, - { - '0', '4', cX0, (KEYMAP *) & cX4map - }, - { - '=', '=', cXeq, NULL - }, - { - '^', 'u', cXcar, NULL - } - } -}; - -static PF metacG[] = { - ctrlg /* ^G */ -}; - -static PF metacV[] = { - pagenext /* ^V */ -}; - -static PF metasp[] = { - justone /* space */ -}; - -static PF metapct[] = { - queryrepl /* % */ -}; - -static PF metami[] = { - poptag, /* * */ - rescan, /* + */ - rescan, /* , */ - negative_argument, /* - */ - findtag, /* . */ - rescan, /* / */ - digit_argument, /* 0 */ - digit_argument, /* 1 */ - digit_argument, /* 2 */ - digit_argument, /* 3 */ - digit_argument, /* 4 */ - digit_argument, /* 5 */ - digit_argument, /* 6 */ - digit_argument, /* 7 */ - digit_argument, /* 8 */ - digit_argument, /* 9 */ - rescan, /* : */ - rescan, /* ; */ - gotobob, /* < */ - rescan, /* = */ - gotoeob /* > */ -}; - -static PF metasqf[] = { - NULL, /* [ */ - delwhite, /* \ */ - rescan, /* ] */ - joinline, /* ^ */ - rescan, /* _ */ - rescan, /* ` */ - rescan, /* a */ - backword, /* b */ - capword, /* c */ - delfword, /* d */ - rescan, /* e */ - forwword /* f */ -}; - -static PF metal[] = { - lowerword, /* l */ - backtoindent, /* m */ - rescan, /* n */ - rescan, /* o */ - rescan, /* p */ - fillpara, /* q */ - backsearch, /* r */ - forwsearch, /* s */ - rescan, /* t */ - upperword, /* u */ - backpage, /* v */ - copyregion, /* w */ - extend, /* x */ - rescan, /* y */ - rescan, /* z */ - gotobop, /* { */ - piperegion, /* | */ - gotoeop /* } */ -}; - -static PF metasqlZ[] = { - rescan /* Z */ -}; - -static PF metatilde[] = { - notmodified, /* ~ */ - delbword /* DEL */ -}; - -struct KEYMAPE (1 + IMAPEXT) metasqlmap = { - 1, - 1 + IMAPEXT, - rescan, - { - { - 'Z', 'Z', metasqlZ, NULL - } - } -}; - -struct KEYMAPE (8 + IMAPEXT) metamap = { - 8, - 8 + IMAPEXT, - rescan, - { - { - CCHR('G'), CCHR('G'), metacG, NULL - }, - { - CCHR('V'), CCHR('V'), metacV, NULL - }, - { - ' ', ' ', metasp, NULL - }, - { - '%', '%', metapct, NULL - }, - { - '*', '>', metami, NULL - }, - { - '[', 'f', metasqf, (KEYMAP *) &metasqlmap - }, - { - 'l', '}', metal, NULL - }, - { - '~', CCHR('?'), metatilde, NULL - } - } -}; - -static PF fund_at[] = { - setmark, /* ^@ */ - gotobol, /* ^A */ - backchar, /* ^B */ - NULL, /* ^C */ - forwdel, /* ^D */ - gotoeol, /* ^E */ - forwchar, /* ^F */ - ctrlg, /* ^G */ -}; - -static PF fund_h[] = { - NULL, /* ^H */ -}; - - -/* ^I is selfinsert */ -static PF fund_CJ[] = { - lfindent, /* ^J */ - killline, /* ^K */ - reposition, /* ^L */ - newline, /* ^M */ - forwline, /* ^N */ - openline, /* ^O */ - backline, /* ^P */ - quote, /* ^Q */ - backisearch, /* ^R */ - forwisearch, /* ^S */ - twiddle, /* ^T */ - universal_argument, /* ^U */ - forwpage, /* ^V */ - killregion, /* ^W */ - NULL, /* ^X */ - yank, /* ^Y */ - spawncli /* ^Z */ -}; - -static PF fund_esc[] = { - NULL, /* esc */ - rescan, /* ^\ selfinsert is default on fundamental */ - rescan, /* ^] */ - rescan, /* ^^ */ - undo /* ^_ */ -}; - -static PF fund_del[] = { - backdel /* DEL */ -}; - -static PF fund_cb[] = { - showmatch /* ) */ -}; - -#ifndef FUND_XMAPS -#define NFUND_XMAPS 0 /* extra map sections after normal ones */ -#endif - -static struct KEYMAPE (6 + NFUND_XMAPS + IMAPEXT) fundmap = { - 6 + NFUND_XMAPS, - 6 + NFUND_XMAPS + IMAPEXT, - selfinsert, - { - { - CCHR('@'), CCHR('G'), fund_at, (KEYMAP *) & ccmap - }, - { - CCHR('H'), CCHR('H'), fund_h, (KEYMAP *) & helpmap - }, - { - CCHR('J'), CCHR('Z'), fund_CJ, (KEYMAP *) & cXmap - }, - { - CCHR('['), CCHR('_'), fund_esc, (KEYMAP *) & metamap - }, - { - ')', ')', fund_cb, NULL - }, - { - CCHR('?'), CCHR('?'), fund_del, NULL - }, -#ifdef FUND_XMAPS - FUND_XMAPS, -#endif /* FUND_XMAPS */ - } -}; - -static PF fill_sp[] = { - fillword /* ' ' */ -}; - -static struct KEYMAPE (1 + IMAPEXT) fillmap = { - 1, - 1 + IMAPEXT, - rescan, - { - { ' ', ' ', fill_sp, NULL } - } -}; - -static PF indent_lf[] = { - newline, /* ^J */ - rescan, /* ^K */ - rescan, /* ^L */ - lfindent /* ^M */ -}; - -static struct KEYMAPE (1 + IMAPEXT) indntmap = { - 1, - 1 + IMAPEXT, - rescan, - { - { - CCHR('J'), CCHR('M'), indent_lf, NULL - } - } -}; - -#ifdef NOTAB -static PF notab_tab[] = { - space_to_tabstop /* ^I */ -}; - -static struct KEYMAPE (1 + IMAPEXT) notabmap = { - 1, - 1 + IMAPEXT, - rescan, - { - { - CCHR('I'), CCHR('I'), notab_tab, NULL - } - } -}; -#endif /* NOTAB */ - -static struct KEYMAPE (1 + IMAPEXT) overwmap = { - 0, - 1 + IMAPEXT, /* 1 to avoid 0 sized array */ - rescan, - { - /* unused dummy entry for VMS C */ - { - (KCHAR)0, (KCHAR)0, NULL, NULL - } - } -}; - - -/* - * The basic (root) keyboard map - */ -struct maps_s fundamental_mode = { (KEYMAP *)&fundmap, "fundamental" }; - -/* - * give names to the maps, for use by help etc. If the map is to be bindable, - * it must also be listed in the function name table below with the same - * name. Maps created dynamically currently don't get added here, thus are - * unnamed. Modes are just named keymaps with functions to add/subtract them - * from a buffer's list of modes. If you change a mode name, change it in - * modes.c also. - */ - -static struct maps_s map_table[] = { - {(KEYMAP *) &fillmap, "fill",}, - {(KEYMAP *) &indntmap, "indent",}, -#ifdef NOTAB - {(KEYMAP *) ¬abmap, "notab",}, -#endif /* NOTAB */ - {(KEYMAP *) &overwmap, "overwrite",}, - {(KEYMAP *) &metamap, "esc prefix",}, - {(KEYMAP *) &cXmap, "c-x prefix",}, - {(KEYMAP *) &cX4map, "c-x 4 prefix",}, - {(KEYMAP *) &helpmap, "help",}, - {NULL, NULL} -}; - -struct maps_s *maps; - -void -maps_init(void) -{ - int i; - struct maps_s *mp; - - maps = &fundamental_mode; - for (i = 0; map_table[i].p_name != NULL; i++) { - mp = &map_table[i]; - mp->p_next = maps; - maps = mp; - } -} - -/* - * Insert a new (named) keymap at the head of the keymap list. - */ -int -maps_add(KEYMAP *map, const char *name) -{ - struct maps_s *mp; - - if ((mp = malloc(sizeof(*mp))) == NULL) - return (FALSE); - - mp->p_name = name; - mp->p_map = map; - mp->p_next = maps; - maps = mp; - - return (TRUE); -} - -struct maps_s * -name_mode(const char *name) -{ - struct maps_s *mp; - - for (mp = maps; mp != NULL; mp = mp->p_next) - if (strcmp(mp->p_name, name) == 0) - return (mp); - return (NULL); -} - -KEYMAP * -name_map(const char *name) -{ - struct maps_s *mp; - - return ((mp = name_mode(name)) == NULL ? NULL : mp->p_map); -} diff --git a/mg/line.c b/mg/line.c deleted file mode 100644 index bafd64f..0000000 --- a/mg/line.c +++ /dev/null @@ -1,635 +0,0 @@ -/* $OpenBSD: line.c,v 1.50 2011/01/18 16:28:00 kjell Exp $ */ - -/* This file is in the public domain. */ - -/* - * Text line handling. - * - * The functions in this file are a general set of line management - * utilities. They are the only routines that touch the text. They - * also touch the buffer and window structures to make sure that the - * necessary updating gets done. There are routines in this file that - * handle the kill buffer too. It isn't here for any good reason. - * - * Note that this code only updates the dot and mark values in the window - * list. Since all the code acts on the current window, the buffer that - * we are editing must be displayed, which means that "b_nwnd" is non-zero, - * which means that the dot and mark values in the buffer headers are - * nonsense. - */ - -#include "def.h" - -#include -#include - -/* - * Allocate a new line of size `used'. lrealloc() can be called if the line - * ever needs to grow beyond that. - */ -struct line * -lalloc(int used) -{ - struct line *lp; - - if ((lp = malloc(sizeof(*lp))) == NULL) - return (NULL); - lp->l_text = NULL; - lp->l_size = 0; - lp->l_used = used; /* XXX */ - if (lrealloc(lp, used) == FALSE) { - free(lp); - return (NULL); - } - return (lp); -} - -int -lrealloc(struct line *lp, int newsize) -{ - char *tmp; - - if (lp->l_size < newsize) { - if ((tmp = realloc(lp->l_text, newsize)) == NULL) - return (FALSE); - lp->l_text = tmp; - lp->l_size = newsize; - } - return (TRUE); -} - -/* - * Delete line "lp". Fix all of the links that might point to it (they are - * moved to offset 0 of the next line. Unlink the line from whatever buffer - * it might be in, and release the memory. The buffers are updated too; the - * magic conditions described in the above comments don't hold here. - */ -void -lfree(struct line *lp) -{ - struct buffer *bp; - struct mgwin *wp; - - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_linep == lp) - wp->w_linep = lp->l_fp; - if (wp->w_dotp == lp) { - wp->w_dotp = lp->l_fp; - wp->w_doto = 0; - } - if (wp->w_markp == lp) { - wp->w_markp = lp->l_fp; - wp->w_marko = 0; - } - } - for (bp = bheadp; bp != NULL; bp = bp->b_bufp) { - if (bp->b_nwnd == 0) { - if (bp->b_dotp == lp) { - bp->b_dotp = lp->l_fp; - bp->b_doto = 0; - } - if (bp->b_markp == lp) { - bp->b_markp = lp->l_fp; - bp->b_marko = 0; - } - } - } - lp->l_bp->l_fp = lp->l_fp; - lp->l_fp->l_bp = lp->l_bp; - if (lp->l_text != NULL) - free(lp->l_text); - free(lp); -} - -/* - * This routine is called when a character changes in place in the current - * buffer. It updates all of the required flags in the buffer and window - * system. The flag used is passed as an argument; if the buffer is being - * displayed in more than 1 window we change EDIT to HARD. Set MODE if the - * mode line needs to be updated (the "*" has to be set). - */ -void -lchange(int flag) -{ - struct mgwin *wp; - - /* update mode lines if this is the first change. */ - if ((curbp->b_flag & BFCHG) == 0) { - flag |= WFMODE; - curbp->b_flag |= BFCHG; - } - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_bufp == curbp) { - wp->w_rflag |= flag; - if (wp != curwp) - wp->w_rflag |= WFFULL; - } - } -} - -/* - * Insert "n" bytes from "s" at the current location of dot. - * In the easy case all that happens is the text is stored in the line. - * In the hard case, the line has to be reallocated. When the window list - * is updated, take special care; I screwed it up once. You always update - * dot in the current window. You update mark and a dot in another window - * if it is greater than the place where you did the insert. Return TRUE - * if all is well, and FALSE on errors. - */ -int -linsert_str(const char *s, int n) -{ - struct line *lp1; - struct mgwin *wp; - RSIZE i; - int doto, k; - - if ((k = checkdirty(curbp)) != TRUE) - return (k); - - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read only"); - return (FALSE); - } - - if (!n) - return (TRUE); - - lchange(WFFULL); - - /* current line */ - lp1 = curwp->w_dotp; - - /* special case for the end */ - if (lp1 == curbp->b_headp) { - struct line *lp2, *lp3; - - /* now should only happen in empty buffer */ - if (curwp->w_doto != 0) - panic("bug: linsert_str"); - /* allocate a new line */ - if ((lp2 = lalloc(n)) == NULL) - return (FALSE); - /* previous line */ - lp3 = lp1->l_bp; - /* link in */ - lp3->l_fp = lp2; - lp2->l_fp = lp1; - lp1->l_bp = lp2; - lp2->l_bp = lp3; - for (i = 0; i < n; ++i) - lp2->l_text[i] = s[i]; - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_linep == lp1) - wp->w_linep = lp2; - if (wp->w_dotp == lp1) - wp->w_dotp = lp2; - if (wp->w_markp == lp1) - wp->w_markp = lp2; - } - undo_add_insert(lp2, 0, n); - curwp->w_doto = n; - return (TRUE); - } - /* save for later */ - doto = curwp->w_doto; - - if ((lp1->l_used + n) > lp1->l_size) { - if (lrealloc(lp1, lp1->l_used + n) == FALSE) - return (FALSE); - } - lp1->l_used += n; - if (lp1->l_used != n) - memmove(&lp1->l_text[doto + n], &lp1->l_text[doto], - lp1->l_used - n - doto); - - /* Add the characters */ - for (i = 0; i < n; ++i) - lp1->l_text[doto + i] = s[i]; - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_dotp == lp1) { - if (wp == curwp || wp->w_doto > doto) - wp->w_doto += n; - } - if (wp->w_markp == lp1) { - if (wp->w_marko > doto) - wp->w_marko += n; - } - } - undo_add_insert(curwp->w_dotp, doto, n); - return (TRUE); -} - -/* - * Insert "n" copies of the character "c" at the current location of dot. - * In the easy case all that happens is the text is stored in the line. - * In the hard case, the line has to be reallocated. When the window list - * is updated, take special care; I screwed it up once. You always update - * dot in the current window. You update mark and a dot in another window - * if it is greater than the place where you did the insert. Return TRUE - * if all is well, and FALSE on errors. - */ -int -linsert(int n, int c) -{ - struct line *lp1; - struct mgwin *wp; - RSIZE i; - int doto; - int s; - - if (!n) - return (TRUE); - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read only"); - return (FALSE); - } - - lchange(WFEDIT); - - /* current line */ - lp1 = curwp->w_dotp; - - /* special case for the end */ - if (lp1 == curbp->b_headp) { - struct line *lp2, *lp3; - - /* now should only happen in empty buffer */ - if (curwp->w_doto != 0) { - ewprintf("bug: linsert"); - return (FALSE); - } - /* allocate a new line */ - if ((lp2 = lalloc(n)) == NULL) - return (FALSE); - /* previous line */ - lp3 = lp1->l_bp; - /* link in */ - lp3->l_fp = lp2; - lp2->l_fp = lp1; - lp1->l_bp = lp2; - lp2->l_bp = lp3; - for (i = 0; i < n; ++i) - lp2->l_text[i] = c; - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_linep == lp1) - wp->w_linep = lp2; - if (wp->w_dotp == lp1) - wp->w_dotp = lp2; - if (wp->w_markp == lp1) - wp->w_markp = lp2; - } - undo_add_insert(lp2, 0, n); - curwp->w_doto = n; - return (TRUE); - } - /* save for later */ - doto = curwp->w_doto; - - if ((lp1->l_used + n) > lp1->l_size) { - if (lrealloc(lp1, lp1->l_used + n) == FALSE) - return (FALSE); - } - lp1->l_used += n; - if (lp1->l_used != n) - memmove(&lp1->l_text[doto + n], &lp1->l_text[doto], - lp1->l_used - n - doto); - - /* Add the characters */ - for (i = 0; i < n; ++i) - lp1->l_text[doto + i] = c; - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_dotp == lp1) { - if (wp == curwp || wp->w_doto > doto) - wp->w_doto += n; - } - if (wp->w_markp == lp1) { - if (wp->w_marko > doto) - wp->w_marko += n; - } - } - undo_add_insert(curwp->w_dotp, doto, n); - return (TRUE); -} - -/* - * Do the work of inserting a newline at the given line/offset. - * If mark is on the current line, we may have to move the markline - * to keep line numbers in sync. - * lnewline_at assumes the current buffer is writable. Checking for - * this fact should be done by the caller. - */ -int -lnewline_at(struct line *lp1, int doto) -{ - struct line *lp2; - int nlen; - struct mgwin *wp; - - lchange(WFFULL); - - curwp->w_bufp->b_lines++; - /* Check if mark is past dot (even on current line) */ - if (curwp->w_markline > curwp->w_dotline || - (curwp->w_dotline == curwp->w_markline && - curwp->w_marko >= doto)) - curwp->w_markline++; - curwp->w_dotline++; - - /* If start of line, allocate a new line instead of copying */ - if (doto == 0) { - /* new first part */ - if ((lp2 = lalloc(0)) == NULL) - return (FALSE); - lp2->l_bp = lp1->l_bp; - lp1->l_bp->l_fp = lp2; - lp2->l_fp = lp1; - lp1->l_bp = lp2; - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) - if (wp->w_linep == lp1) - wp->w_linep = lp2; - undo_add_boundary(FFRAND, 1); - undo_add_insert(lp2, 0, 1); - undo_add_boundary(FFRAND, 1); - return (TRUE); - } - - /* length of new part */ - nlen = llength(lp1) - doto; - - /* new second half line */ - if ((lp2 = lalloc(nlen)) == NULL) - return (FALSE); - if (nlen != 0) - bcopy(&lp1->l_text[doto], &lp2->l_text[0], nlen); - lp1->l_used = doto; - lp2->l_bp = lp1; - lp2->l_fp = lp1->l_fp; - lp1->l_fp = lp2; - lp2->l_fp->l_bp = lp2; - /* Windows */ - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_dotp == lp1 && wp->w_doto >= doto) { - wp->w_dotp = lp2; - wp->w_doto -= doto; - } - if (wp->w_markp == lp1 && wp->w_marko >= doto) { - wp->w_markp = lp2; - wp->w_marko -= doto; - } - } - undo_add_boundary(FFRAND, 1); - undo_add_insert(lp1, llength(lp1), 1); - undo_add_boundary(FFRAND, 1); - return (TRUE); -} - -/* - * Insert a newline into the buffer at the current location of dot in the - * current window. - */ -int -lnewline(void) -{ - int s; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read only"); - return (FALSE); - } - return (lnewline_at(curwp->w_dotp, curwp->w_doto)); -} - -/* - * This function deletes "n" bytes, starting at dot. (actually, n+1, as the - * newline is included) It understands how to deal with end of lines, etc. - * It returns TRUE if all of the characters were deleted, and FALSE if - * they were not (because dot ran into the end of the buffer). - * The "kflag" indicates either no insertion, or direction of insertion - * into the kill buffer. - */ -int -ldelete(RSIZE n, int kflag) -{ - struct line *dotp; - RSIZE chunk; - struct mgwin *wp; - int doto; - char *cp1, *cp2; - size_t len; - char *sv = NULL; - int end; - int s; - int rval = FALSE; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read only"); - goto out; - } - len = n; - if ((sv = calloc(1, len + 1)) == NULL) - goto out; - end = 0; - - undo_add_delete(curwp->w_dotp, curwp->w_doto, n, (kflag & KREG)); - - while (n != 0) { - dotp = curwp->w_dotp; - doto = curwp->w_doto; - /* Hit the end of the buffer */ - if (dotp == curbp->b_headp) - goto out; - /* Size of the chunk */ - chunk = dotp->l_used - doto; - - if (chunk > n) - chunk = n; - /* End of line, merge */ - if (chunk == 0) { - if (dotp == blastlp(curbp)) - goto out; - lchange(WFFULL); - if (ldelnewline() == FALSE) - goto out; - end = strlcat(sv, "\n", len + 1); - --n; - continue; - } - lchange(WFEDIT); - /* Scrunch text */ - cp1 = &dotp->l_text[doto]; - memcpy(&sv[end], cp1, chunk); - end += chunk; - sv[end] = '\0'; - for (cp2 = cp1 + chunk; cp2 < &dotp->l_text[dotp->l_used]; - cp2++) - *cp1++ = *cp2; - dotp->l_used -= (int)chunk; - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_dotp == dotp && wp->w_doto >= doto) { - /* NOSTRICT */ - wp->w_doto -= chunk; - if (wp->w_doto < doto) - wp->w_doto = doto; - } - if (wp->w_markp == dotp && wp->w_marko >= doto) { - /* NOSTRICT */ - wp->w_marko -= chunk; - if (wp->w_marko < doto) - wp->w_marko = doto; - } - } - n -= chunk; - } - if (kchunk(sv, (RSIZE)len, kflag) != TRUE) - goto out; - rval = TRUE; -out: - free(sv); - return (rval); -} - -/* - * Delete a newline and join the current line with the next line. If the next - * line is the magic header line always return TRUE; merging the last line - * with the header line can be thought of as always being a successful - * operation. Even if nothing is done, this makes the kill buffer work - * "right". If the mark is past the dot (actually, markline > dotline), - * decrease the markline accordingly to keep line numbers in sync. - * Easy cases can be done by shuffling data around. Hard cases - * require that lines be moved about in memory. Return FALSE on error and - * TRUE if all looks ok. We do not update w_dotline here, as deletes are done - * after moves. - */ -int -ldelnewline(void) -{ - struct line *lp1, *lp2, *lp3; - struct mgwin *wp; - int s; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read only"); - return (FALSE); - } - - lp1 = curwp->w_dotp; - lp2 = lp1->l_fp; - /* at the end of the buffer */ - if (lp2 == curbp->b_headp) - return (TRUE); - /* Keep line counts in sync */ - curwp->w_bufp->b_lines--; - if (curwp->w_markline > curwp->w_dotline) - curwp->w_markline--; - if (lp2->l_used <= lp1->l_size - lp1->l_used) { - bcopy(&lp2->l_text[0], &lp1->l_text[lp1->l_used], lp2->l_used); - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_linep == lp2) - wp->w_linep = lp1; - if (wp->w_dotp == lp2) { - wp->w_dotp = lp1; - wp->w_doto += lp1->l_used; - } - if (wp->w_markp == lp2) { - wp->w_markp = lp1; - wp->w_marko += lp1->l_used; - } - } - lp1->l_used += lp2->l_used; - lp1->l_fp = lp2->l_fp; - lp2->l_fp->l_bp = lp1; - free(lp2); - return (TRUE); - } - if ((lp3 = lalloc(lp1->l_used + lp2->l_used)) == NULL) - return (FALSE); - bcopy(&lp1->l_text[0], &lp3->l_text[0], lp1->l_used); - bcopy(&lp2->l_text[0], &lp3->l_text[lp1->l_used], lp2->l_used); - lp1->l_bp->l_fp = lp3; - lp3->l_fp = lp2->l_fp; - lp2->l_fp->l_bp = lp3; - lp3->l_bp = lp1->l_bp; - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_linep == lp1 || wp->w_linep == lp2) - wp->w_linep = lp3; - if (wp->w_dotp == lp1) - wp->w_dotp = lp3; - else if (wp->w_dotp == lp2) { - wp->w_dotp = lp3; - wp->w_doto += lp1->l_used; - } - if (wp->w_markp == lp1) - wp->w_markp = lp3; - else if (wp->w_markp == lp2) { - wp->w_markp = lp3; - wp->w_marko += lp1->l_used; - } - } - free(lp1); - free(lp2); - return (TRUE); -} - -/* - * Replace plen characters before dot with argument string. Control-J - * characters in st are interpreted as newlines. There is a casehack - * disable flag (normally it likes to match case of replacement to what - * was there). - */ -int -lreplace(RSIZE plen, char *st) -{ - RSIZE rlen; /* replacement length */ - int s; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read only"); - return (FALSE); - } - undo_boundary_enable(FFRAND, 0); - - (void)backchar(FFARG | FFRAND, (int)plen); - (void)ldelete(plen, KNONE); - - rlen = strlen(st); - region_put_data(st, rlen); - lchange(WFFULL); - - undo_boundary_enable(FFRAND, 1); - return (TRUE); -} - -/* - * Allocate and return the supplied line as a C string - */ -char * -linetostr(const struct line *ln) -{ - int len; - char *line; - - len = llength(ln); - if (len == INT_MAX) /* (len + 1) overflow */ - return (NULL); - - if ((line = malloc(len + 1)) == NULL) - return (NULL); - - (void)memcpy(line, ltext(ln), len); - line[len] = '\0'; - - return (line); -} diff --git a/mg/macro.c b/mg/macro.c deleted file mode 100644 index 1910478..0000000 --- a/mg/macro.c +++ /dev/null @@ -1,106 +0,0 @@ -/* $OpenBSD: macro.c,v 1.14 2012/04/12 04:47:59 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Keyboard macros. - */ - -#include "def.h" -#include "key.h" -#include "macro.h" - -int inmacro = FALSE; /* Macro playback in progess */ -int macrodef = FALSE; /* Macro recording in progress */ -int macrocount = 0; - -struct line *maclhead = NULL; -struct line *maclcur; - -union macrodef macro[MAXMACRO]; - -/* ARGSUSED */ -int -definemacro(int f, int n) -{ - struct line *lp1, *lp2; - - macrocount = 0; - - if (macrodef) { - ewprintf("already defining macro"); - return (macrodef = FALSE); - } - - /* free lines allocated for string arguments */ - if (maclhead != NULL) { - for (lp1 = maclhead->l_fp; lp1 != maclhead; lp1 = lp2) { - lp2 = lp1->l_fp; - free(lp1); - } - free(lp1); - } - - if ((maclhead = lp1 = lalloc(0)) == NULL) - return (FALSE); - - ewprintf("Defining Keyboard Macro..."); - maclcur = lp1->l_fp = lp1->l_bp = lp1; - return (macrodef = TRUE); -} - -/* ARGSUSED */ -int -finishmacro(int f, int n) -{ - if (macrodef == TRUE) { - macrodef = FALSE; - ewprintf("End Keyboard Macro Definition"); - return (TRUE); - } - return (FALSE); -} - -/* ARGSUSED */ -int -executemacro(int f, int n) -{ - int i, j, flag, num; - PF funct; - - if (macrodef || - (macrocount >= MAXMACRO && macro[MAXMACRO - 1].m_funct - != finishmacro)) { - ewprintf("Macro too long. Aborting."); - return (FALSE); - } - - if (macrocount == 0) - return (TRUE); - - inmacro = TRUE; - - for (i = n; i > 0; i--) { - maclcur = maclhead->l_fp; - flag = 0; - num = 1; - for (j = 0; j < macrocount - 1; j++) { - funct = macro[j].m_funct; - if (funct == universal_argument) { - flag = FFARG; - num = macro[++j].m_count; - continue; - } - if ((*funct)(flag, num) != TRUE) { - inmacro = FALSE; - return (FALSE); - } - lastflag = thisflag; - thisflag = 0; - flag = 0; - num = 1; - } - } - inmacro = FALSE; - return (TRUE); -} diff --git a/mg/macro.h b/mg/macro.h deleted file mode 100644 index 52cc83d..0000000 --- a/mg/macro.h +++ /dev/null @@ -1,21 +0,0 @@ -/* $OpenBSD: macro.h,v 1.7 2005/11/18 20:56:53 deraadt Exp $ */ - -/* This file is in the public domain. */ - -/* definitions for keyboard macros */ - -#define MAXMACRO 256 /* maximum functs in a macro */ - -extern int inmacro; -extern int macrodef; -extern int macrocount; - -union macrodef { - PF m_funct; - int m_count; /* for count-prefix */ -}; - -extern union macrodef macro[MAXMACRO]; - -extern struct line *maclhead; -extern struct line *maclcur; diff --git a/mg/main.c b/mg/main.c deleted file mode 100644 index c93eb9f..0000000 --- a/mg/main.c +++ /dev/null @@ -1,245 +0,0 @@ -/* $OpenBSD: main.c,v 1.67 2012/05/29 06:08:48 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Mainline. - */ - -#include "def.h" -#include "kbd.h" -#include "funmap.h" -#include "macro.h" - -#include - -int thisflag; /* flags, this command */ -int lastflag; /* flags, last command */ -int curgoal; /* goal column */ -int startrow; /* row to start */ -struct buffer *curbp; /* current buffer */ -struct buffer *bheadp; /* BUFFER list head */ -struct mgwin *curwp; /* current window */ -struct mgwin *wheadp; /* MGWIN listhead */ -char pat[NPAT]; /* pattern */ - -static void edinit(struct buffer *); -static __dead void usage(void); - -extern char *__progname; -extern void closetags(void); - -static __dead void -usage() -{ - fprintf(stderr, "usage: %s [-n] [-f mode] [+number] [file ...]\n", - __progname); - exit(1); -} - -int -main(int argc, char **argv) -{ - char *cp, *init_fcn_name = NULL; - PF init_fcn = NULL; - int o, i, nfiles; - int nobackups = 0; - struct buffer *bp = NULL; - - while ((o = getopt(argc, argv, "nf:")) != -1) - switch (o) { - case 'n': - nobackups = 1; - break; - case 'f': - if (init_fcn_name != NULL) - errx(1, "cannot specify more than one " - "initial function"); - init_fcn_name = optarg; - break; - default: - usage(); - } - argc -= optind; - argv += optind; - - maps_init(); /* Keymaps and modes. */ - funmap_init(); /* Functions. */ - - /* - * This is where we initialize standalone extensions that should - * be loaded dynamically sometime in the future. - */ - { - extern void grep_init(void); - extern void theo_init(void); - extern void cmode_init(void); - extern void dired_init(void); - - dired_init(); - grep_init(); - theo_init(); - cmode_init(); - } - - if (init_fcn_name && - (init_fcn = name_function(init_fcn_name)) == NULL) - errx(1, "Unknown function `%s'", init_fcn_name); - - vtinit(); /* Virtual terminal. */ - dirinit(); /* Get current directory. */ - edinit(bp); /* Buffers, windows. */ - ttykeymapinit(); /* Symbols, bindings. */ - - /* - * doing update() before reading files causes the error messages from - * the file I/O show up on the screen. (and also an extra display of - * the mode line if there are files specified on the command line.) - */ - update(); - - /* user startup file. */ - if ((cp = startupfile(NULL)) != NULL) - (void)load(cp); - - /* - * Now ensure any default buffer modes from the startup file are - * given to any files opened when parsing the startup file. - * Note *scratch* will also be updated. - */ - for (bp = bheadp; bp != NULL; bp = bp->b_bufp) { - bp->b_flag = defb_flag; - for (i = 0; i <= defb_nmodes; i++) { - bp->b_modes[i] = defb_modes[i]; - } - } - - /* Force FFOTHARG=1 so that this mode is enabled, not simply toggled */ - if (init_fcn) - init_fcn(FFOTHARG, 1); - - if (nobackups) - makebkfile(FFARG, 0); - - for (nfiles = 0, i = 0; i < argc; i++) { - if (argv[i][0] == '+' && strlen(argv[i]) >= 2) { - long long lval; - const char *errstr; - - lval = strtonum(&argv[i][1], INT_MIN, INT_MAX, &errstr); - if (argv[i][1] == '\0' || errstr != NULL) - goto notnum; - startrow = lval; - } else { -notnum: - cp = adjustname(argv[i], FALSE); - if (cp != NULL) { - if (nfiles == 1) - splitwind(0, 1); - - if ((curbp = findbuffer(cp)) == NULL) { - vttidy(); - errx(1, "Can't find current buffer!"); - } - (void)showbuffer(curbp, curwp, 0); - if (readin(cp) != TRUE) - killbuffer(curbp); - else { - /* Ensure enabled, not just toggled */ - if (init_fcn_name) - init_fcn(FFOTHARG, 1); - nfiles++; - } - } - } - } - - if (nfiles > 2) - listbuffers(0, 1); - - /* fake last flags */ - thisflag = 0; - for (;;) { - if (epresf == KCLEAR) - eerase(); - if (epresf == TRUE) - epresf = KCLEAR; - if (winch_flag) { - do_redraw(0, 0, TRUE); - winch_flag = 0; - } - update(); - lastflag = thisflag; - thisflag = 0; - - switch (doin()) { - case TRUE: - break; - case ABORT: - ewprintf("Quit"); - /* FALLTHRU */ - case FALSE: - default: - ttbeep(); - macrodef = FALSE; - } - } -} - -/* - * Initialize default buffer and window. Default buffer is called *scratch*. - */ -static void -edinit(struct buffer *bp) -{ - struct mgwin *wp; - - bheadp = NULL; - bp = bfind("*scratch*", TRUE); /* Text buffer. */ - if (bp == NULL) - panic("edinit"); - - wp = new_window(bp); - if (wp == NULL) - panic("edinit: Out of memory"); - - curbp = bp; /* Current buffer. */ - wheadp = wp; - curwp = wp; - wp->w_wndp = NULL; /* Initialize window. */ - wp->w_linep = wp->w_dotp = bp->b_headp; - wp->w_ntrows = nrow - 2; /* 2 = mode, echo. */ - wp->w_rflag = WFMODE | WFFULL; /* Full. */ -} - -/* - * Quit command. If an argument, always quit. Otherwise confirm if a buffer - * has been changed and not written out. Normally bound to "C-X C-C". - */ -/* ARGSUSED */ -int -quit(int f, int n) -{ - int s; - - if ((s = anycb(FALSE)) == ABORT) - return (ABORT); - if (s == FALSE - || eyesno("Modified buffers exist; really exit") == TRUE) { - vttidy(); - closetags(); - exit(GOOD); - } - return (TRUE); -} - -/* - * User abort. Should be called by any input routine that sees a C-g to abort - * whatever C-g is aborting these days. Currently does nothing. - */ -/* ARGSUSED */ -int -ctrlg(int f, int n) -{ - return (ABORT); -} diff --git a/mg/match.c b/mg/match.c deleted file mode 100644 index 4c5d0c3..0000000 --- a/mg/match.c +++ /dev/null @@ -1,185 +0,0 @@ -/* $OpenBSD: match.c,v 1.16 2009/06/04 02:23:37 kjell Exp $ */ - -/* This file is in the public domain. */ - -/* - * Limited parenthesis matching routines - * - * The hacks in this file implement automatic matching * of (), [], {}, and - * other characters. It would be better to have a full-blown syntax table, - * but there's enough overhead in the editor as it is. - */ - -#include "def.h" -#include "key.h" - -static int balance(void); -static void displaymatch(struct line *, int); - -/* - * Balance table. When balance() encounters a character that is to be - * matched, it first searches this table for a balancing left-side character. - * If the character is not in the table, the character is balanced by itself. - */ -static struct balance { - char left, right; -} bal[] = { - { '(', ')' }, - { '[', ']' }, - { '{', '}' }, - { '<', '>' }, - { '\0', '\0' } -}; - -/* - * Hack to show matching paren. Self-insert character, then show matching - * character, if any. Bound to "blink-and-insert". - */ -int -showmatch(int f, int n) -{ - int i, s; - - for (i = 0; i < n; i++) { - if ((s = selfinsert(FFRAND, 1)) != TRUE) - return (s); - /* unbalanced -- warn user */ - if (balance() != TRUE) - ttbeep(); - } - return (TRUE); -} - -/* - * Search for and display a matching character. - * - * This routine does the real work of searching backward - * for a balancing character. If such a balancing character - * is found, it uses displaymatch() to display the match. - */ -static int -balance(void) -{ - struct line *clp; - int cbo; - int c, i, depth; - int rbal, lbal; - - rbal = key.k_chars[key.k_count - 1]; - - /* See if there is a matching character -- default to the same */ - lbal = rbal; - for (i = 0; bal[i].right != '\0'; i++) - if (bal[i].right == rbal) { - lbal = bal[i].left; - break; - } - - /* - * Move behind the inserted character. We are always guaranteed - * that there is at least one character on the line, since one was - * just self-inserted by blinkparen. - */ - clp = curwp->w_dotp; - cbo = curwp->w_doto - 1; - - /* init nesting depth */ - depth = 0; - - for (;;) { - if (cbo == 0) { - clp = lback(clp); /* beginning of line */ - if (clp == curbp->b_headp) - return (FALSE); - cbo = llength(clp) + 1; - } - if (--cbo == llength(clp)) - c = '\n'; /* end of line */ - else - c = lgetc(clp, cbo); /* somewhere in middle */ - - /* - * Check for a matching character. If still in a nested - * level, pop out of it and continue search. This check - * is done before the nesting check so single-character - * matches will work too. - */ - if (c == lbal) { - if (depth == 0) { - displaymatch(clp, cbo); - return (TRUE); - } else - depth--; - } - /* Check for another level of nesting. */ - if (c == rbal) - depth++; - } - /* NOTREACHED */ -} - -/* - * Display matching character. Matching characters that are not in the - * current window are displayed in the echo line. If in the current window, - * move dot to the matching character, sit there a while, then move back. - */ -static void -displaymatch(struct line *clp, int cbo) -{ - struct line *tlp; - int tbo; - int cp; - int bufo; - int c; - int inwindow; - char buf[NLINE]; - - /* - * Figure out if matching char is in current window by - * searching from the top of the window to dot. - */ - inwindow = FALSE; - for (tlp = curwp->w_linep; tlp != lforw(curwp->w_dotp); - tlp = lforw(tlp)) - if (tlp == clp) - inwindow = TRUE; - - if (inwindow == TRUE) { - tlp = curwp->w_dotp; /* save current position */ - tbo = curwp->w_doto; - - curwp->w_dotp = clp; /* move to new position */ - curwp->w_doto = cbo; - curwp->w_rflag |= WFMOVE; - - update(); /* show match */ - ttwait(1000); /* wait for key or 1 second */ - - curwp->w_dotp = tlp; /* return to old position */ - curwp->w_doto = tbo; - curwp->w_rflag |= WFMOVE; - update(); - } else { - /* match is not in this window, so display line in echo area */ - bufo = 0; - for (cp = 0; cp < llength(clp); cp++) { - c = lgetc(clp, cp); - if (c != '\t' -#ifdef NOTAB - || (curbp->b_flag & BFNOTAB) -#endif - ) - if (ISCTRL(c)) { - buf[bufo++] = '^'; - buf[bufo++] = CCHR(c); - } else - buf[bufo++] = c; - else - do { - buf[bufo++] = ' '; - } while (bufo & 7); - } - buf[bufo++] = '\0'; - ewprintf("Matches %s", buf); - } -} diff --git a/mg/mg.1 b/mg/mg.1 deleted file mode 100644 index 134af55..0000000 --- a/mg/mg.1 +++ /dev/null @@ -1,956 +0,0 @@ -.\" $OpenBSD: mg.1,v 1.68 2012/07/11 19:56:13 sobrado Exp $ -.\" This file is in the public domain. -.\" -.Dd $Mdocdate: July 11 2012 $ -.Dt MG 1 -.Os -.Sh NAME -.Nm mg -.Nd emacs-like text editor -.Sh SYNOPSIS -.Nm mg -.Op Fl n -.Op Fl f Ar mode -.Op + Ns Ar number -.Op Ar -.Sh DESCRIPTION -.Nm -is intended to be a small, fast, and portable editor for -people who can't (or don't want to) run emacs for one -reason or another, or are not familiar with the -.Xr vi 1 -editor. -It is compatible with emacs because there shouldn't -be any reason to learn more editor types than emacs or -.Xr vi 1 . -.Pp -The options are as follows: -.Bl -tag -width Ds -.It + Ns Ar number -Go to the line specified by number (do not insert -a space between the -.Sq + -sign and the number). -If a negative number is specified, the line number counts -backwards from the end of the file i.e. +-1 will be the last -line of the file, +-2 will be second last, and so on. -.It Fl f Ar mode -Run the mode command for all buffers created from -arguments on the command line, including the -scratch buffer and all files. -.It Fl n -Turn off backup file generation. -.El -.Sh WINDOWS AND BUFFERS -When a file is loaded into -.Nm , -it is stored in a -.Em buffer . -This buffer may be displayed on the screen in more than one window. -At present, windows may only be split horizontally, so each window is -delineated by a modeline at the bottom. -If changes are made to a buffer, it will be reflected in all open windows. -.Pp -If a buffer name begins and ends with an asterisk, the buffer is considered -throwaway; i.e. the user will not be prompted to save changes when -the buffer is killed. -.Sh POINT AND MARK -The current cursor location in -.Nm -is called the -.Em point -(or -.Em dot ) . -It is possible to define a window-specific region of text by setting a second -location, called the -.Em mark . -The -.Em region -is the text between point and mark inclusive. -Deleting the character at the mark position leaves -the mark at the point of deletion. -.Pp -Note: The point and mark are window-specific in -.Nm , -not buffer-specific, as in other emacs flavours. -.Sh BACKUP FILES -Backup files have a -.Sq ~ -character appended to the file name and -are created in the current working directory by default. -Whether to create backup files or not can be toggled with the -make-backup-file command. -The backup file location can either be in the current -working directory, or all backups can be moved to a -.Pa ~/.mg.d -directory where files retain their path name to retain uniqueness. -Use the backup-to-home-directory to alternate between these two locations. -Further, if any application creates backup files in the -.Ev TMPDIR , -these can be left with the leave-tmpdir-backups command. -.Sh TAGS -.Nm -supports tag files created by -.Xr ctags 1 , -allowing the user to quickly locate various object definitions. -Note though that emacs uses etags, not ctags. -.Sh CSCOPE -.Nm -supports navigating source code using cscope. -However, -.Nm -requires cscope and cscope-indexer executables to be present in -.Ev PATH -for it to work. -.Sh DEFAULT KEY BINDINGS -Normal editing commands are very similar to GNU Emacs. -In the following examples, C-x means Control-x, and M-x means Meta-x, -where the Meta key may be either a special key on the keyboard -or the ALT key; otherwise ESC followed by the key X works as well. -.Pp -.Bl -tag -width xxxxxxxxxxxx -offset indent -compact -.It C-SPC -set-mark-command -.It C-a -beginning-of-line -.It C-b -backward-char -.It C-c s c -cscope-find-functions-calling-this-function -.It C-c s d -cscope-find-global-definition -.It C-c s e -cscope-find-egrep-pattern -.It C-c s f -cscope-find-this-file -.It C-c s i -cscope-find-files-including-file -.It C-c s n -cscope-next-symbol -.It C-c s p -cscope-prev-symbol -.It C-c s s -cscope-find-this-symbol -.It C-c s t -cscope-find-this-text-string -.It C-d -delete-char -.It C-e -end-of-line -.It C-f -forward-char -.It C-g -keyboard-quit -.It C-h C-h -help-help -.It C-h a -apropos -.It C-h b -describe-bindings -.It C-h c -describe-key-briefly -.It C-j -newline-and-indent -.It C-k -kill-line -.It C-l -recenter -.It RET -newline -.It C-n -next-line -.It C-o -open-line -.It C-p -previous-line -.It C-q -quoted-insert -.It C-r -isearch-backward -.It C-s -isearch-forward -.It C-t -transpose-chars -.It C-u -universal-argument -.It C-v -scroll-up -.It C-w -kill-region -.It C-x C-b -list-buffers -.It C-x C-c -save-buffers-kill-emacs -.It C-x C-f -find-file -.It C-x C-g -keyboard-quit -.It C-x C-l -downcase-region -.It C-x C-o -delete-blank-lines -.It C-x C-q -toggle-read-only -.It C-x C-r -find-file-read-only -.It C-x C-s -save-buffer -.It C-x C-u -upcase-region -.It C-x C-v -find-alternate-file -.It C-x C-w -write-file -.It C-x C-x -exchange-point-and-mark -.It C-x ( -start-kbd-macro -.It C-x \&) -end-kbd-macro -.It C-x 0 -delete-window -.It C-x 1 -delete-other-windows -.It C-x 2 -split-window-vertically -.It C-x 4 C-f -find-file-other-window -.It C-x 4 C-g -keyboard-quit -.It C-x 4 b -switch-to-buffer-other-window -.It C-x 4 f -find-file-other-window -.It C-x = -what-cursor-position -.It C-x ^ -enlarge-window -.It C-x ` -next-error -.It C-x b -switch-to-buffer -.It C-x d -dired -.It C-x e -call-last-kbd-macro -.It C-x f -set-fill-column -.It C-x g -goto-line -.It C-x h -mark-whole-buffer -.It C-x i -insert-file -.It C-x k -kill-buffer -.It C-x n -other-window -.It C-x o -other-window -.It C-x p -previous-window -.It C-x s -save-some-buffers -.It C-x u -undo -.It C-y -yank -.It C-z -suspend-emacs -.It M-C-v -scroll-other-window -.It M-SPC -just-one-space -.It M-. -find-tag -.It M-* -pop-tag-mark -.It M-% -query-replace -.It M-< -beginning-of-buffer -.It M-> -end-of-buffer -.It M-\e -delete-horizontal-space -.It M-^ -join-line -.It M-b -backward-word -.It M-c -capitalize-word -.It M-d -kill-word -.It M-f -forward-word -.It M-l -downcase-word -.It M-m -back-to-indentation -.It M-q -fill-paragraph -.It M-r -search-backward -.It M-s -search-forward -.It M-u -upcase-word -.It M-v -scroll-down -.It M-w -copy-region-as-kill -.It M-x -execute-extended-command -.It M-{ -backward-paragraph -.It M-| -shell-command-on-region -.It M-} -forward-paragraph -.It M-~ -not-modified -.It M-DEL -backward-kill-word -.It C-_ -undo -.It ) -blink-and-insert -.It DEL -delete-backward-char -.El -.Pp -For a complete description of -.Nm -commands, see -.Sx MG COMMANDS . -To see the active keybindings at any time, type -.Dq M-x describe-bindings . -.Sh MG COMMANDS -Commands are invoked by -.Dq M-x , -or by binding to a key. -Many commands take an optional numerical parameter, -.Va n . -This parameter is set either by -M- (where -.Va n -is the numerical argument) before the command, or by -one or more invocations of the universal argument, usually bound to C-u. -When invoked in this manner, the value of the numeric parameter to -be passed is displayed in the minibuffer before the M-x. -One common use of the parameter is in mode toggles (e.g.\& -make-backup-files). -If no parameter is supplied, the mode is toggled to its -alternate state. -If a positive parameter is supplied, the mode is forced to on. -Otherwise, it is forced to off. -.\" -.Bl -tag -width xxxxx -.It apropos -Help Apropos. -Prompt the user for a string, open the *help* buffer, -and list all -.Nm -commands that contain that string. -.It auto-execute -Register an auto-execute hook; that is, specify a filename pattern -(conforming to the shell's filename globbing rules) and an associated -function to execute when a file matching the specified pattern -is read into a buffer. -.It auto-fill-mode -Toggle auto-fill mode (sometimes called mail-mode), -where text inserted past the fill column is automatically wrapped -to a new line. -.It auto-indent-mode -Toggle indent mode, where indentation is preserved after a newline. -.It back-to-indentation -Move the dot to the first non-whitespace character on the current line. -.It backup-to-home-directory -Save backup copies to a -.Pa ~/.mg.d -directory instead of working directory. -Requires make-backup-files to be on. -.It backward-char -Move cursor backwards one character. -.It backward-kill-word -Kill text backwards by -.Va n -words. -.It backward-paragraph -Move cursor backwards -.Va n -paragraphs. -Paragraphs are delimited by or or . -.It backward-word -Move cursor backwards by the specified number of words. -.It beginning-of-buffer -Move cursor to the top of the buffer. -.It beginning-of-line -Move cursor to the beginning of the line. -.It blink-and-insert -Self-insert a character, then search backwards and blink its -matching delimiter. -For delimiters other than -parenthesis, brackets, and braces, the character itself -is used as its own match. -.It bsmap-mode -Toggle bsmap mode, where DEL and C-h are swapped. -.It c-mode -Toggle a KNF-compliant mode for editing C program files. -.It call-last-kbd-macro -Invoke the keyboard macro. -.It capitalize-word -Capitalize -.Va n -words; i.e. convert the first character of the word to -upper case, and subsequent letters to lower case. -.It cd -Change the global working directory. -See also global-wd-mode. -.It copy-region-as-kill -Copy all of the characters in the region to the kill buffer, -clearing the mark afterwards. -This is a bit like a kill-region followed by a yank. -.It count-matches -Count the number of lines matching the supplied regular expression. -.It count-non-matches -Count the number of lines not matching the supplied regular expression. -.It cscope-find-this-symbol -List the matches for the given symbol. -.It cscope-find-global-definition -List global definitions for the given literal. -.It cscope-find-called-functions -List functions called from the given function. -.It cscope-find-functions-calling-this-function -List functions calling the given function. -.It cscope-find-this-text-string -List locations matching the given text string. -.It cscope-find-egrep-pattern -List locations matching the given extended regular expression pattern. -.It cscope-find-this-file -List filenames matching the given filename. -.It cscope-find-files-including-file -List files that #include the given filename. -.It cscope-next-symbol -Navigate to the next match. -.It cscope-prev-symbol -Navigate to the previous match. -.It cscope-next-file -Navigate to the next file. -.It cscope-prev-file -Navigate to the previous file. -.It cscope-create-list-of-files-to-index -Create cscope's List and Index in the given directory. -.It define-key -Prompts the user for a named keymap (mode), -a key, and an -.Nm -command, then creates a keybinding in the appropriate -map. -.It delete-backward-char -Delete backwards -.Va n -characters. -Like delete-char, this actually does a kill if presented -with an argument. -.It delete-blank-lines -Delete blank lines around dot. -If dot is sitting on a blank line, this command -deletes all the blank lines above and below the current line. -Otherwise, it deletes all of the blank lines after the current line. -.It delete-char -Delete -.Va n -characters forward. -If any argument is present, it kills rather than deletes, -saving the result in the kill buffer. -.It delete-horizontal-space -Delete any whitespace around the dot. -.It delete-leading-space -Delete leading whitespace on the current line. -.It delete-trailing-space -Delete trailing whitespace on the current line. -.It delete-matching-lines -Delete all lines after dot that contain a string matching -the supplied regular expression. -.It delete-non-matching-lines -Delete all lines after dot that contain a string matching -the supplied regular expression. -.It delete-other-windows -Make the current window the only window visible on the screen. -.It delete-window -Delete current window. -.It describe-bindings -List all global and local keybindings, putting the result in -the *help* buffer. -.It describe-key-briefly -Read a key from the keyboard, and look it up in the keymap. -Display the name of the function currently bound to the key. -.It digit-argument -Process a numerical argument for keyboard-invoked functions. -.It downcase-region -Set all characters in the region to lower case. -.It downcase-word -Set characters to lower case, starting at the dot, and ending -.Va n -words away. -.It emacs-version -Return an -.Nm -version string. -.It end-kbd-macro -Stop defining a keyboard macro. -.It end-of-buffer -Move cursor to the end of the buffer. -.It end-of-line -Move cursor to the end of the line. -.It enlarge-window -Enlarge the current window by shrinking either the window above -or below it. -.It eval-current-buffer -Evaluate the current buffer as a series of -.Nm -commands. -Useful for testing -.Nm -startup files. -.It eval-expression -Get one line from the user, and run it. -Useful for testing expressions in -.Nm -startup files. -.It exchange-point-and-mark -Swap the values of "dot" and "mark" in the current window. -Return an error if no mark is set. -.It execute-extended-command -Invoke an extended command; i.e. M-x. -Call the message line routine to read in the command name and apply -autocompletion to it. -When it comes back, look the name up in the symbol table and run the -command if it is found, passing arguments as necessary. -Print an error if there is anything wrong. -.It fill-paragraph -Justify a paragraph, wrapping text at the current fill column. -.It find-file -Select a file for editing. -First check if the file can be found -in another buffer; if it is there, just switch to that buffer. -If the file cannot be found, create a new buffer, read in the -file from disk, and switch to the new buffer. -.It find-file-read-only -Same as find-file, except the new buffer is set to read-only. -.It find-alternate-file -Replace the current file with an alternate one. -Semantics for finding the replacement file are the same as -find-file, except the current buffer is killed before the switch. -If the kill fails, or is aborted, revert to the original file. -.It find-file-other-window -Opens the specified file in a second buffer. -Splits the current window if necessary. -.It find-tag -Jump to definition of tag at dot. -.It forward-char -Move cursor forwards (or backwards, if -.Va n -is negative) -.Va n -characters. -Returns an error if the end of buffer is reached. -.It forward-paragraph -Move forward -.Va n -paragraphs. -Paragraphs are delimited by or or . -.It forward-word -Move the cursor forward by the specified number of words. -.It global-set-key -Bind a key in the global (fundamental) key map. -.It global-unset-key -Unbind a key from the global (fundamental) key map; i.e. set it to 'rescan'. -.It global-wd-mode -Toggle global working-directory mode. -When enabled, -.Nm -defaults to opening files (and executing commands like compile and grep) -relative to the global working directory. -When disabled, a working directory is set for each buffer. -.It goto-line -Go to a specific line. -If an argument is present, then -it is the line number, else prompt for a line number to use. -.It help-help -Prompts for one of (a)propos, (b)indings, des(c)ribe key briefly. -.It insert -Insert a string, mainly for use from macros. -.It insert-buffer -Insert the contents of another buffer at dot. -.It insert-file -Insert a file into the current buffer at dot. -.It insert-with-wrap -Insert the bound character with word wrap. -Check to see if we're past the fill column, and if so, -justify this line. -.It isearch-backward -Use incremental searching, initially in the reverse direction. -isearch ignores any explicit arguments. -If invoked during macro definition or evaluation, the non-incremental -search-backward is invoked instead. -.It isearch-forward -Use incremental searching, initially in the forward direction. -isearch ignores any explicit arguments. -If invoked during macro definition or evaluation, the non-incremental -search-forward is invoked instead. -.It join-line -Join the current line to the previous. -If called with an argument, -join the next line to the current one. -.It just-one-space -Delete any whitespace around dot, then insert a space. -.It keyboard-quit -Abort the current action. -.It kill-buffer -Dispose of a buffer, by name. -If the buffer name does not start and end with an asterisk, -prompt the user if the buffer -has been changed. -.It kill-line -Kill line. -If called without an argument, it kills from dot to the end -of the line, unless it is at the end of the line, when it kills the -newline. -If called with an argument of 0, it kills from the start of the -line to dot. -If called with a positive argument, it kills from dot -forward over that number of newlines. -If called with a negative argument -it kills any text before dot on the current line, then it kills back -abs(n) lines. -.It kill-paragraph -Delete -.Va n -paragraphs starting with the current one. -.It kill-region -Kill the currently defined region. -.It kill-word -Delete forward -.Va n -words. -.It leave-tmpdir-backups -Modifies the behaviour of backup-to-home-directory. -Backup files that would normally reside in the system -.Ev TMPDIR -are left there and not moved to the -.Pa ~/.mg.d -directory. -.It line-number-mode -Toggle whether line and column numbers are displayed in the modeline. -.It list-buffers -Display the list of available buffers. -.It load -Prompt the user for a filename, and then execute commands -from that file. -.It local-set-key -Bind a key mapping in the local (topmost) mode. -.It local-unset-key -Unbind a key mapping in the local (topmost) mode. -.It make-backup-files -Toggle generation of backup files. -.It mark-whole-buffer -Marks whole buffer as a region by putting dot at the beginning and mark -at the end of buffer. -.It meta-key-mode -When disabled, the meta key can be used to insert extended-ascii (8-bit) -characters. -When enabled, the meta key acts as usual. -.It negative-argument -Process a negative argument for keyboard-invoked functions. -.It newline -Insert a newline into the current buffer. -.It newline-and-indent -Insert a newline, then enough tabs and spaces to duplicate the indentation -of the previous line. -Assumes tabs are every eight characters. -.It next-line -Move forward -.Va n -lines. -.It no-tab-mode -Toggle notab mode. -In this mode, spaces are inserted rather than tabs. -.It not-modified -Turn off the modified flag in the current buffer. -.It open-line -Open up some blank space. -Essentially, insert -.Va n -newlines, then back up over them. -.It other-window -The command to make the next (down the screen) window the current -window. -There are no real errors, although the command does nothing if -there is only 1 window on the screen. -.It overwrite-mode -Toggle overwrite mode, where typing in a buffer overwrites -existing characters rather than inserting them. -.It prefix-region -Inserts a prefix string before each line of a region. -The prefix string is settable by using 'set-prefix-string'. -.It previous-line -Move backwards -.Va n -lines. -.It previous-window -This command makes the previous (up the screen) window the -current window. -There are no errors, although the command does not do -a lot if there is only 1 window. -.It pop-tag-mark -Return to position where find-tag was previously invoked. -.It push-shell -Suspend -.Nm -and switch to alternate screen, if available. -.It pwd -Display current (global) working directory in the status area. -.It query-replace -Query Replace. -Search and replace strings selectively, prompting after each match. -.It replace-string -Replace string globally without individual prompting. -.It query-replace-regexp -Replace strings selectively. -Does a search and replace operation using regular -expressions for both patterns. -.It quoted-insert -Insert the next character verbatim into the current buffer; i.e. ignore -any function bound to that key. -.It re-search-again -Perform a regular expression search again, using the same search -string and direction as the last search command. -.It re-search-backward -Search backwards using a regular expression. -Get a search string from the user, and search, starting at dot -and proceeding toward the front of the buffer. -If found, dot is left -pointing at the first character of the pattern [the last character that -was matched]. -.It re-search-forward -Search forward using a regular expression. -Get a search string from the user and search for it starting at dot. -If found, move dot to just after the matched characters. -display does all -the hard stuff. -If not found, it just prints a message. -.It recenter -Reposition dot in the current window. -By default, the dot is centered. -If given a positive argument (n), the display is repositioned to line -n. -If -.Va n -is negative, it is that line from the bottom. -.It redraw-display -Refresh the display. -Recomputes all window sizes in case something has changed. -.It save-buffer -Save the contents of the current buffer if it has been changed, -optionally creating a backup copy. -.It save-buffers-kill-emacs -Offer to save modified buffers and quit -.Nm . -.It save-some-buffers -Look through the list of buffers, offering to save any buffer that -has been changed. -Buffers that are not associated with files (such -as *scratch*, *grep*, *compile*) are ignored. -.It scroll-down -Scroll backwards -.Va n -pages. -A two-line overlap between pages is -assumed. -If given a repeat argument, scrolls back lines, not pages. -.It scroll-one-line-down -Scroll the display down -.Va n -lines without changing the cursor position. -.It scroll-one-line-up -Scroll the display -.Va n -lines up without moving the cursor position. -.It scroll-other-window -Scroll the next window in the window list window forward -.Va n -pages. -.It scroll-up -Scroll forward one page. -A two-line overlap between pages is -assumed. -If given a repeat argument, scrolls back lines, not pages. -.It search-again -Search again, using the same search string and direction as the last -search command. -.It search-backward -Reverse search. -Get a search string from the user, and search, starting -at dot and proceeding toward the front of the buffer. -If found, dot is -left pointing at the first character of the pattern (the last character -that was matched). -.It search-forward -Search forward. -Get a search string from the user, and search for it -starting at dot. -If found, dot gets moved to just after the matched -characters, if not found, print a message. -.It self-insert-command -Insert a character. -.It set-case-fold-search -Set case-fold searching, causing case not to matter -in regular expression searches. -This is the default. -.It set-default-mode -Append the supplied mode to the list of default modes -used by subsequent buffer creation. -Built in modes include: fill, indent, overwrite, and notab. -.It set-fill-column -Prompt the user for a fill column. -Used by auto-fill-mode. -.It set-mark-command -Sets the mark in the current window to the current dot location. -.It set-prefix-string -Sets the prefix string to be used by the 'prefix-region' command. -.It shell-command-on-region -Provide the text in region to the shell command as input. -.It shrink-window -Shrink current window by one line. -The window immediately below is expanded to pick up the slack. -If only one window is present, this command has no effect. -.It space-to-tabstop -Insert enough spaces to reach the next tab-stop position. -By default, tab-stops occur every 8 characters. -.It split-window-vertically -Split the current window. -A window smaller than 3 lines cannot be split. -.It start-kbd-macro -Start defining a keyboard macro. -Macro definition is ended by invoking end-kbd-macro. -.It suspend-emacs -Suspend -.Nm -and switch back to alternate screen, if in use. -.It switch-to-buffer -Prompt and switch to a new buffer in the current window. -.It switch-to-buffer-other-window -Switch to buffer in another window. -.It toggle-read-only -Toggle the read-only flag on the current buffer. -.It transpose-chars -Transpose the two characters on either side of dot. -If dot is at the end of the line, transpose the two characters before it. -Return with an error if dot is at the beginning of line; -it seems to be a bit pointless to -make this work. -.It undo -Undo the most recent action. -If invoked again without an intervening command, -move the undo pointer to the previous action and undo it. -.It undo-boundary -Add an undo boundary. -This is not usually done interactively. -.It undo-boundary-toggle -Toggle whether undo boundaries are generated. -Undo boundaries are often disabled before operations that should -be considered atomically undoable. -.It undo-enable -Toggle whether undo information is kept. -.It undo-list -Show the undo records for the current buffer in a new buffer. -.It universal-argument -Repeat the next command 4 times. -Usually bound to C-u. -This command may be stacked; e.g.\& -C-u C-u C-f moves the cursor forward 16 characters. -.It upcase-region -Upper case region. -Change all of the lower case characters in the region to -upper case. -.It upcase-word -Move the cursor forward by the specified number of words. -As it moves, convert any characters to upper case. -.It visit-tags-table -Record name of the tags file to be used for subsequent find-tag. -.It what-cursor-position -Display a bunch of useful information about the current location of -dot. -The character under the cursor (in octal), the current line, row, -and column, and approximate position of the cursor in the file (as a -percentage) is displayed. -The column position assumes an infinite -position display; it does not truncate just because the screen does. -.It write-file -Ask for a file name and write the contents of the current buffer to -that file. -Update the remembered file name and clear the buffer -changed flag. -.It yank -Yank text from kill-buffer. -Unlike emacs, the -.Nm -kill buffer consists only -of the most recent kill. -It is not a ring. -.El -.Sh CONFIGURATION FILES -There are two configuration files, -.Pa .mg -and -.Pa .mg-TERM . -Here, -.Ev TERM -represents the name of the terminal type; e.g. if the terminal type -is set to -.Dq vt100 , -.Nm -will use -.Pa .mg-vt100 -as a startup file. -The terminal type startup file is used first. -.Pp -The startup file format is a list of commands, one per line, as used for -interactive evaluation. -Strings that are normally entered by the user at any subsequent prompts -may be specified after the command name; e.g.: -.Bd -literal -offset indent -global-set-key ")" self-insert-command -global-set-key "\e^x\e^f" find-file -global-set-key "\ee[Z" backward-char -set-default-mode fill -set-fill-column 72 -auto-execute *.c c-mode -.Ed -.Sh FILES -.Bl -tag -width /usr/share/doc/mg/tutorial -compact -.It Pa ~/.mg -normal startup file -.It Pa ~/.mg-TERM -terminal-specific startup file -.It Pa ~/.mg.d -alternative backup file location -.It Pa /usr/share/doc/mg/tutorial -concise tutorial -.El -.Sh SEE ALSO -.Xr ctags 1 , -.Xr vi 1 -.Sh CAVEATS -Since it is written completely in C, there is currently no -language in which extensions can be written; -however, keys can be rebound and certain parameters can be changed -in startup files. -.Pp -In order to use 8-bit characters (such as German umlauts), the Meta key -needs to be disabled via the -.Dq meta-key-mode -command. - diff --git a/mg/modes.c b/mg/modes.c deleted file mode 100644 index cde8728..0000000 --- a/mg/modes.c +++ /dev/null @@ -1,165 +0,0 @@ -/* $OpenBSD: modes.c,v 1.18 2008/06/14 08:46:30 kjell Exp $ */ - -/* This file is in the public domain. */ - -/* - * Commands to toggle modes. Without an argument, these functions will - * toggle the given mode. A negative or zero argument will turn the mode - * off. A positive argument will turn the mode on. - */ - -#include "def.h" -#include "kbd.h" - -int changemode(int, int, char *); - -int defb_nmodes = 0; -struct maps_s *defb_modes[PBMODES] = { &fundamental_mode }; -int defb_flag = 0; - -int -changemode(int f, int n, char *mode) -{ - int i; - struct maps_s *m; - - if ((m = name_mode(mode)) == NULL) { - ewprintf("Can't find mode %s", mode); - return (FALSE); - } - if (!(f & FFARG)) { - for (i = 0; i <= curbp->b_nmodes; i++) - if (curbp->b_modes[i] == m) { - /* mode already set */ - n = 0; - break; - } - } - if (n > 0) { - for (i = 0; i <= curbp->b_nmodes; i++) - if (curbp->b_modes[i] == m) - /* mode already set */ - return (TRUE); - if (curbp->b_nmodes >= PBMODES - 1) { - ewprintf("Too many modes"); - return (FALSE); - } - curbp->b_modes[++(curbp->b_nmodes)] = m; - } else { - /* fundamental is b_modes[0] and can't be unset */ - for (i = 1; i <= curbp->b_nmodes && m != curbp->b_modes[i]; - i++); - if (i > curbp->b_nmodes) - return (TRUE); /* mode wasn't set */ - for (; i < curbp->b_nmodes; i++) - curbp->b_modes[i] = curbp->b_modes[i + 1]; - curbp->b_nmodes--; - } - upmodes(curbp); - return (TRUE); -} - -int -indentmode(int f, int n) -{ - return (changemode(f, n, "indent")); -} - -int -fillmode(int f, int n) -{ - return (changemode(f, n, "fill")); -} - -#ifdef NOTAB -int -notabmode(int f, int n) -{ - if (changemode(f, n, "notab") == FALSE) - return (FALSE); - if (f & FFARG) { - if (n <= 0) - curbp->b_flag &= ~BFNOTAB; - else - curbp->b_flag |= BFNOTAB; - } else - curbp->b_flag ^= BFNOTAB; - return (TRUE); -} -#endif /* NOTAB */ - -int -overwrite_mode(int f, int n) -{ - if (changemode(f, n, "overwrite") == FALSE) - return (FALSE); - if (f & FFARG) { - if (n <= 0) - curbp->b_flag &= ~BFOVERWRITE; - else - curbp->b_flag |= BFOVERWRITE; - } else - curbp->b_flag ^= BFOVERWRITE; - return (TRUE); -} - -int -set_default_mode(int f, int n) -{ - int i; - struct maps_s *m; - char modebuf[32], *bufp; - - if ((bufp = eread("Set Default Mode: ", modebuf, sizeof(modebuf), - EFNEW)) == NULL) - return (ABORT); - else if (bufp[0] == '\0') - return (FALSE); - if ((m = name_mode(modebuf)) == NULL) { - ewprintf("can't find mode %s", modebuf); - return (FALSE); - } - if (!(f & FFARG)) { - for (i = 0; i <= defb_nmodes; i++) - if (defb_modes[i] == m) { - /* mode already set */ - n = 0; - break; - } - } - if (n > 0) { - for (i = 0; i <= defb_nmodes; i++) - if (defb_modes[i] == m) - /* mode already set */ - return (TRUE); - if (defb_nmodes >= PBMODES - 1) { - ewprintf("Too many modes"); - return (FALSE); - } - defb_modes[++defb_nmodes] = m; - } else { - /* fundamental is defb_modes[0] and can't be unset */ - for (i = 1; i <= defb_nmodes && m != defb_modes[i]; i++); - if (i > defb_nmodes) - /* mode was not set */ - return (TRUE); - for (; i < defb_nmodes; i++) - defb_modes[i] = defb_modes[i + 1]; - defb_nmodes--; - } - if (strcmp(modebuf, "overwrite") == 0) { - if (n <= 0) - defb_flag &= ~BFOVERWRITE; - else - defb_flag |= BFOVERWRITE; - } -#ifdef NOTAB - if (strcmp(modebuf, "notab") == 0) { - if (n <= 0) - defb_flag &= ~BFNOTAB; - else - defb_flag |= BFNOTAB; - } -#endif /* NOTAB */ - return (TRUE); -} diff --git a/mg/paragraph.c b/mg/paragraph.c deleted file mode 100644 index 57ce412..0000000 --- a/mg/paragraph.c +++ /dev/null @@ -1,362 +0,0 @@ -/* $OpenBSD: paragraph.c,v 1.22 2011/11/29 05:59:54 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Code for dealing with paragraphs and filling. Adapted from MicroEMACS 3.6 - * and GNU-ified by mwm@ucbvax. Several bug fixes by blarson@usc-oberon. - */ - -#include "def.h" - -static int fillcol = 70; - -#define MAXWORD 256 - -/* - * Move to start of paragraph. Go back to the beginning of the current - * paragraph here we look for a or or - * combination to delimit the beginning of a paragraph. - */ -/* ARGSUSED */ -int -gotobop(int f, int n) -{ - /* the other way... */ - if (n < 0) - return (gotoeop(f, -n)); - - while (n-- > 0) { - /* first scan back until we are in a word */ - while (backchar(FFRAND, 1) && inword() == 0); - - /* and go to the B-O-Line */ - curwp->w_doto = 0; - - /* - * and scan back until we hit a or - * - */ - while (lback(curwp->w_dotp) != curbp->b_headp) - if (llength(lback(curwp->w_dotp)) && - lgetc(curwp->w_dotp, 0) != ' ' && - lgetc(curwp->w_dotp, 0) != '.' && - lgetc(curwp->w_dotp, 0) != '\t') - curwp->w_dotp = lback(curwp->w_dotp); - else { - if (llength(lback(curwp->w_dotp)) && - lgetc(curwp->w_dotp, 0) == '.') { - curwp->w_dotp = lforw(curwp->w_dotp); - if (curwp->w_dotp == curbp->b_headp) { - /* - * beyond end of buffer, - * cleanup time - */ - curwp->w_dotp = - lback(curwp->w_dotp); - curwp->w_doto = - llength(curwp->w_dotp); - } - } - break; - } - } - /* force screen update */ - curwp->w_rflag |= WFMOVE; - return (TRUE); -} - -/* - * Move to end of paragraph. Go forward to the end of the current paragraph - * here we look for a or or combination to - * delimit the beginning of a paragraph. - */ -/* ARGSUSED */ -int -gotoeop(int f, int n) -{ - /* the other way... */ - if (n < 0) - return (gotobop(f, -n)); - - /* for each one asked for */ - while (n-- > 0) { - /* Find the first word on/after the current line */ - curwp->w_doto = 0; - while (forwchar(FFRAND, 1) && inword() == 0); - - curwp->w_doto = 0; - curwp->w_dotp = lforw(curwp->w_dotp); - - /* and scan forword until we hit a or ... */ - while (curwp->w_dotp != curbp->b_headp) { - if (llength(curwp->w_dotp) && - lgetc(curwp->w_dotp, 0) != ' ' && - lgetc(curwp->w_dotp, 0) != '.' && - lgetc(curwp->w_dotp, 0) != '\t') - curwp->w_dotp = lforw(curwp->w_dotp); - else - break; - } - if (curwp->w_dotp == curbp->b_headp) { - /* beyond end of buffer, cleanup time */ - curwp->w_dotp = lback(curwp->w_dotp); - curwp->w_doto = llength(curwp->w_dotp); - break; - } - } - /* force screen update */ - curwp->w_rflag |= WFMOVE; - return (TRUE); -} - -/* - * Justify a paragraph. Fill the current paragraph according to the current - * fill column. - */ -/* ARGSUSED */ -int -fillpara(int f, int n) -{ - int c; /* current char during scan */ - int wordlen; /* length of current word */ - int clength; /* position on line during fill */ - int i; /* index during word copy */ - int eopflag; /* Are we at the End-Of-Paragraph? */ - int firstflag; /* first word? (needs no space) */ - int newlength; /* tentative new line length */ - int eolflag; /* was at end of line */ - int retval; /* return value */ - struct line *eopline; /* pointer to line just past EOP */ - char wbuf[MAXWORD]; /* buffer for current word */ - - undo_boundary_enable(FFRAND, 0); - - /* record the pointer to the line just past the EOP */ - (void)gotoeop(FFRAND, 1); - if (curwp->w_doto != 0) { - /* paragraph ends at end of buffer */ - (void)lnewline(); - eopline = lforw(curwp->w_dotp); - } else - eopline = curwp->w_dotp; - - /* and back top the begining of the paragraph */ - (void)gotobop(FFRAND, 1); - - /* initialize various info */ - while (inword() == 0 && forwchar(FFRAND, 1)); - - clength = curwp->w_doto; - wordlen = 0; - - /* scan through lines, filling words */ - firstflag = TRUE; - eopflag = FALSE; - while (!eopflag) { - - /* get the next character in the paragraph */ - if ((eolflag = (curwp->w_doto == llength(curwp->w_dotp)))) { - c = ' '; - if (lforw(curwp->w_dotp) == eopline) - eopflag = TRUE; - } else - c = lgetc(curwp->w_dotp, curwp->w_doto); - - /* and then delete it */ - if (ldelete((RSIZE) 1, KNONE) == FALSE && !eopflag) { - retval = FALSE; - goto cleanup; - } - - /* if not a separator, just add it in */ - if (c != ' ' && c != '\t') { - if (wordlen < MAXWORD - 1) - wbuf[wordlen++] = c; - else { - /* - * You lose chars beyond MAXWORD if the word - * is too long. I'm too lazy to fix it now; it - * just silently truncated the word before, - * so I get to feel smug. - */ - ewprintf("Word too long!"); - } - } else if (wordlen) { - - /* calculate tentative new length with word added */ - newlength = clength + 1 + wordlen; - - /* - * if at end of line or at doublespace and previous - * character was one of '.','?','!' doublespace here. - * behave the same way if a ')' is preceded by a - * [.?!] and followed by a doublespace. - */ - if ((eolflag || - curwp->w_doto == llength(curwp->w_dotp) || - (c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' - || c == '\t') && (ISEOSP(wbuf[wordlen - 1]) || - (wbuf[wordlen - 1] == ')' && wordlen >= 2 && - ISEOSP(wbuf[wordlen - 2]))) && - wordlen < MAXWORD - 1) - wbuf[wordlen++] = ' '; - - /* at a word break with a word waiting */ - if (newlength <= fillcol) { - /* add word to current line */ - if (!firstflag) { - (void)linsert(1, ' '); - ++clength; - } - firstflag = FALSE; - } else { - if (curwp->w_doto > 0 && - lgetc(curwp->w_dotp, curwp->w_doto - 1) == ' ') { - curwp->w_doto -= 1; - (void)ldelete((RSIZE) 1, KNONE); - } - /* start a new line */ - (void)lnewline(); - clength = 0; - } - - /* and add the word in in either case */ - for (i = 0; i < wordlen; i++) { - (void)linsert(1, wbuf[i]); - ++clength; - } - wordlen = 0; - } - } - /* and add a last newline for the end of our new paragraph */ - (void)lnewline(); - - /* - * We really should wind up where we started, (which is hard to keep - * track of) but I think the end of the last line is better than the - * beginning of the blank line. - */ - (void)backchar(FFRAND, 1); - retval = TRUE; -cleanup: - undo_boundary_enable(FFRAND, 1); - return (retval); -} - -/* - * Delete a paragraph. Delete n paragraphs starting with the current one. - */ -/* ARGSUSED */ -int -killpara(int f, int n) -{ - int status; /* returned status of functions */ - - /* for each paragraph to delete */ - while (n--) { - - /* mark out the end and beginning of the para to delete */ - (void)gotoeop(FFRAND, 1); - - /* set the mark here */ - curwp->w_markp = curwp->w_dotp; - curwp->w_marko = curwp->w_doto; - - /* go to the beginning of the paragraph */ - (void)gotobop(FFRAND, 1); - - /* force us to the beginning of line */ - curwp->w_doto = 0; - - /* and delete it */ - if ((status = killregion(FFRAND, 1)) != TRUE) - return (status); - - /* and clean up the 2 extra lines */ - (void)ldelete((RSIZE) 1, KFORW); - } - return (TRUE); -} - -/* - * Insert char with work wrap. Check to see if we're past fillcol, and if so, - * justify this line. As a last step, justify the line. - */ -/* ARGSUSED */ -int -fillword(int f, int n) -{ - char c; - int col, i, nce; - - for (i = col = 0; col <= fillcol; ++i, ++col) { - if (i == curwp->w_doto) - return selfinsert(f, n); - c = lgetc(curwp->w_dotp, i); - if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif - ) - col |= 0x07; - else if (ISCTRL(c) != FALSE) - ++col; - } - if (curwp->w_doto != llength(curwp->w_dotp)) { - (void)selfinsert(f, n); - nce = llength(curwp->w_dotp) - curwp->w_doto; - } else - nce = 0; - curwp->w_doto = i; - - if ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' && c != '\t') - do { - (void)backchar(FFRAND, 1); - } while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' && - c != '\t' && curwp->w_doto > 0); - - if (curwp->w_doto == 0) - do { - (void)forwchar(FFRAND, 1); - } while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' && - c != '\t' && curwp->w_doto < llength(curwp->w_dotp)); - - (void)delwhite(FFRAND, 1); - (void)lnewline(); - i = llength(curwp->w_dotp) - nce; - curwp->w_doto = i > 0 ? i : 0; - curwp->w_rflag |= WFMOVE; - if (nce == 0 && curwp->w_doto != 0) - return (fillword(f, n)); - return (TRUE); -} - -/* - * Set fill column to n for justify. - */ -int -setfillcol(int f, int n) -{ - char buf[32], *rep; - const char *es; - int nfill; - - if ((f & FFARG) != 0) { - fillcol = n; - } else { - if ((rep = eread("Set fill-column: ", buf, sizeof(buf), - EFNEW | EFCR)) == NULL) - return (ABORT); - else if (rep[0] == '\0') - return (FALSE); - nfill = strtonum(rep, 0, INT_MAX, &es); - if (es != NULL) { - ewprintf("Invalid fill column: %s", rep); - return (FALSE); - } - fillcol = nfill; - ewprintf("Fill column set to %d", fillcol); - } - return (TRUE); -} diff --git a/mg/pathnames.h b/mg/pathnames.h deleted file mode 100644 index 9720076..0000000 --- a/mg/pathnames.h +++ /dev/null @@ -1,11 +0,0 @@ -/* $OpenBSD: pathnames.h,v 1.1 2012/06/18 07:14:55 jasper Exp $ */ - -/* This file is in the public domain. */ - -/* - * standard path names - */ - -#define _PATH_MG_DIR "~/.mg.d" -#define _PATH_MG_STARTUP "%s/.mg" -#define _PATH_MG_TERM "%s/.mg-%s" diff --git a/mg/random.c b/mg/random.c deleted file mode 100644 index 27fd0c3..0000000 --- a/mg/random.c +++ /dev/null @@ -1,496 +0,0 @@ -/* $OpenBSD: random.c,v 1.31 2012/05/18 02:13:44 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Assorted commands. - * This file contains the command processors for a large assortment of - * unrelated commands. The only thing they have in common is that they - * are all command processors. - */ - -#include "def.h" - -#include - -/* - * Display a bunch of useful information about the current location of dot. - * The character under the cursor (in octal), the current line, row, and - * column, and approximate position of the cursor in the file (as a - * percentage) is displayed. The column position assumes an infinite - * position display; it does not truncate just because the screen does. - * This is normally bound to "C-X =". - */ -/* ARGSUSED */ -int -showcpos(int f, int n) -{ - struct line *clp; - long nchar, cchar; - int nline, row; - int cline, cbyte; /* Current line/char/byte */ - int ratio; - - /* collect the data */ - clp = bfirstlp(curbp); - cchar = 0; - cline = 0; - cbyte = 0; - nchar = 0; - nline = 0; - for (;;) { - /* count this line */ - ++nline; - if (clp == curwp->w_dotp) { - /* mark line */ - cline = nline; - cchar = nchar + curwp->w_doto; - if (curwp->w_doto == llength(clp)) - cbyte = '\n'; - else - cbyte = lgetc(clp, curwp->w_doto); - } - /* now count the chars */ - nchar += llength(clp); - clp = lforw(clp); - if (clp == curbp->b_headp) - break; - /* count the newline */ - nchar++; - } - /* determine row */ - row = curwp->w_toprow + 1; - clp = curwp->w_linep; - while (clp != curbp->b_headp && clp != curwp->w_dotp) { - ++row; - clp = lforw(clp); - } - /* NOSTRICT */ - ratio = nchar ? (100L * cchar) / nchar : 100; - ewprintf("Char: %c (0%o) point=%ld(%d%%) line=%d row=%d col=%d", - cbyte, cbyte, cchar, ratio, cline, row, getcolpos()); - return (TRUE); -} - -int -getcolpos(void) -{ - int col, i, c; - char tmp[5]; - - /* determine column */ - col = 0; - - for (i = 0; i < curwp->w_doto; ++i) { - c = lgetc(curwp->w_dotp, i); - if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif /* NOTAB */ - ) { - col |= 0x07; - col++; - } else if (ISCTRL(c) != FALSE) - col += 2; - else if (isprint(c)) { - col++; - } else { - col += snprintf(tmp, sizeof(tmp), "\\%o", c); - } - - } - return (col); -} - -/* - * Twiddle the two characters on either side of dot. If dot is at the end - * of the line twiddle the two characters before it. Return with an error - * if dot is at the beginning of line; it seems to be a bit pointless to - * make this work. This fixes up a very common typo with a single stroke. - * Normally bound to "C-T". This always works within a line, so "WFEDIT" - * is good enough. - */ -/* ARGSUSED */ -int -twiddle(int f, int n) -{ - struct line *dotp; - int doto, cr; - int fudge = FALSE; - - dotp = curwp->w_dotp; - doto = curwp->w_doto; - if (doto == llength(dotp)) { - if (--doto <= 0) - return (FALSE); - (void)backchar(FFRAND, 1); - fudge = TRUE; - } else { - if (doto == 0) - return (FALSE); - } - undo_boundary_enable(FFRAND, 0); - cr = lgetc(dotp, doto - 1); - (void)backdel(FFRAND, 1); - (void)forwchar(FFRAND, 1); - linsert(1, cr); - if (fudge != TRUE) - (void)backchar(FFRAND, 1); - undo_boundary_enable(FFRAND, 1); - lchange(WFEDIT); - return (TRUE); -} - -/* - * Open up some blank space. The basic plan is to insert a bunch of - * newlines, and then back up over them. Everything is done by the - * subcommand processors. They even handle the looping. Normally this - * is bound to "C-O". - */ -/* ARGSUSED */ -int -openline(int f, int n) -{ - int i, s; - - if (n < 0) - return (FALSE); - if (n == 0) - return (TRUE); - - /* insert newlines */ - undo_boundary_enable(FFRAND, 0); - i = n; - do { - s = lnewline(); - } while (s == TRUE && --i); - - /* then go back up overtop of them all */ - if (s == TRUE) - s = backchar(f | FFRAND, n); - undo_boundary_enable(FFRAND, 1); - return (s); -} - -/* - * Insert a newline. - */ -/* ARGSUSED */ -int -newline(int f, int n) -{ - int s; - - if (n < 0) - return (FALSE); - - while (n--) { - if ((s = lnewline()) != TRUE) - return (s); - } - return (TRUE); -} - -/* - * Delete blank lines around dot. What this command does depends if dot is - * sitting on a blank line. If dot is sitting on a blank line, this command - * deletes all the blank lines above and below the current line. If it is - * sitting on a non blank line then it deletes all of the blank lines after - * the line. Normally this command is bound to "C-X C-O". Any argument is - * ignored. - */ -/* ARGSUSED */ -int -deblank(int f, int n) -{ - struct line *lp1, *lp2; - RSIZE nld; - - lp1 = curwp->w_dotp; - while (llength(lp1) == 0 && (lp2 = lback(lp1)) != curbp->b_headp) - lp1 = lp2; - lp2 = lp1; - nld = (RSIZE)0; - while ((lp2 = lforw(lp2)) != curbp->b_headp && llength(lp2) == 0) - ++nld; - if (nld == 0) - return (TRUE); - curwp->w_dotp = lforw(lp1); - curwp->w_doto = 0; - return (ldelete((RSIZE)nld, KNONE)); -} - -/* - * Delete any whitespace around dot, then insert a space. - */ -int -justone(int f, int n) -{ - undo_boundary_enable(FFRAND, 0); - (void)delwhite(f, n); - linsert(1, ' '); - undo_boundary_enable(FFRAND, 1); - return (TRUE); -} - -/* - * Delete any whitespace around dot. - */ -/* ARGSUSED */ -int -delwhite(int f, int n) -{ - int col, s; - - col = curwp->w_doto; - - while (col < llength(curwp->w_dotp) && - (isspace(lgetc(curwp->w_dotp, col)))) - ++col; - do { - if (curwp->w_doto == 0) { - s = FALSE; - break; - } - if ((s = backchar(FFRAND, 1)) != TRUE) - break; - } while (isspace(lgetc(curwp->w_dotp, curwp->w_doto))); - - if (s == TRUE) - (void)forwchar(FFRAND, 1); - (void)ldelete((RSIZE)(col - curwp->w_doto), KNONE); - return (TRUE); -} - -/* - * Delete any leading whitespace on the current line - */ -int -delleadwhite(int f, int n) -{ - int soff, ls; - struct line *slp; - - /* Save current position */ - slp = curwp->w_dotp; - soff = curwp->w_doto; - - for (ls = 0; ls < llength(slp); ls++) - if (!isspace(lgetc(slp, ls))) - break; - gotobol(FFRAND, 1); - forwdel(FFRAND, ls); - soff -= ls; - if (soff < 0) - soff = 0; - forwchar(FFRAND, soff); - - return (TRUE); -} - -/* - * Delete any trailing whitespace on the current line - */ -int -deltrailwhite(int f, int n) -{ - int soff; - - /* Save current position */ - soff = curwp->w_doto; - - gotoeol(FFRAND, 1); - delwhite(FFRAND, 1); - - /* restore original position, if possible */ - if (soff < curwp->w_doto) - curwp->w_doto = soff; - - return (TRUE); -} - - - -/* - * Insert a newline, then enough tabs and spaces to duplicate the indentation - * of the previous line. Assumes tabs are every eight characters. Quite - * simple. Figure out the indentation of the current line. Insert a newline - * by calling the standard routine. Insert the indentation by inserting the - * right number of tabs and spaces. Return TRUE if all ok. Return FALSE if - * one of the subcommands failed. Normally bound to "C-M". - */ -/* ARGSUSED */ -int -lfindent(int f, int n) -{ - int c, i, nicol; - int s = TRUE; - - if (n < 0) - return (FALSE); - - undo_boundary_enable(FFRAND, 0); - while (n--) { - nicol = 0; - for (i = 0; i < llength(curwp->w_dotp); ++i) { - c = lgetc(curwp->w_dotp, i); - if (c != ' ' && c != '\t') - break; - if (c == '\t') - nicol |= 0x07; - ++nicol; - } - if (lnewline() == FALSE || (( -#ifdef NOTAB - curbp->b_flag & BFNOTAB) ? linsert(nicol, ' ') == FALSE : ( -#endif /* NOTAB */ - ((i = nicol / 8) != 0 && linsert(i, '\t') == FALSE) || - ((i = nicol % 8) != 0 && linsert(i, ' ') == FALSE)))) { - s = FALSE; - break; - } - } - undo_boundary_enable(FFRAND, 1); - return (s); -} - -/* - * Indent the current line. Delete existing leading whitespace, - * and use tabs/spaces to achieve correct indentation. Try - * to leave dot where it started. - */ -int -indent(int f, int n) -{ - int soff, i; - - if (n < 0) - return (FALSE); - - delleadwhite(FFRAND, 1); - - /* If not invoked with a numerical argument, done */ - if (!(f & FFARG)) - return (TRUE); - - /* insert appropriate whitespace */ - soff = curwp->w_doto; - (void)gotobol(FFRAND, 1); - if ( -#ifdef NOTAB - (curbp->b_flag & BFNOTAB) ? linsert(n, ' ') == FALSE : -#endif /* NOTAB */ - (((i = n / 8) != 0 && linsert(i, '\t') == FALSE) || - ((i = n % 8) != 0 && linsert(i, ' ') == FALSE))) - return (FALSE); - - forwchar(FFRAND, soff); - - return (TRUE); -} - - -/* - * Delete forward. This is real easy, because the basic delete routine does - * all of the work. Watches for negative arguments, and does the right thing. - * If any argument is present, it kills rather than deletes, to prevent loss - * of text if typed with a big argument. Normally bound to "C-D". - */ -/* ARGSUSED */ -int -forwdel(int f, int n) -{ - if (n < 0) - return (backdel(f | FFRAND, -n)); - - /* really a kill */ - if (f & FFARG) { - if ((lastflag & CFKILL) == 0) - kdelete(); - thisflag |= CFKILL; - } - - return (ldelete((RSIZE) n, (f & FFARG) ? KFORW : KNONE)); -} - -/* - * Delete backwards. This is quite easy too, because it's all done with - * other functions. Just move the cursor back, and delete forwards. Like - * delete forward, this actually does a kill if presented with an argument. - */ -/* ARGSUSED */ -int -backdel(int f, int n) -{ - int s; - - if (n < 0) - return (forwdel(f | FFRAND, -n)); - - /* really a kill */ - if (f & FFARG) { - if ((lastflag & CFKILL) == 0) - kdelete(); - thisflag |= CFKILL; - } - if ((s = backchar(f | FFRAND, n)) == TRUE) - s = ldelete((RSIZE)n, (f & FFARG) ? KFORW : KNONE); - - return (s); -} - -#ifdef NOTAB -/* ARGSUSED */ -int -space_to_tabstop(int f, int n) -{ - if (n < 0) - return (FALSE); - if (n == 0) - return (TRUE); - return (linsert((n << 3) - (curwp->w_doto & 7), ' ')); -} -#endif /* NOTAB */ - -/* - * Move the dot to the first non-whitespace character of the current line. - */ -int -backtoindent(int f, int n) -{ - gotobol(FFRAND, 1); - while (curwp->w_doto < llength(curwp->w_dotp) && - (isspace(lgetc(curwp->w_dotp, curwp->w_doto)))) - ++curwp->w_doto; - return (TRUE); -} - -/* - * Join the current line to the previous, or with arg, the next line - * to the current one. If the former line is not empty, leave exactly - * one space at the joint. Otherwise, leave no whitespace. - */ -int -joinline(int f, int n) -{ - int doto; - - undo_boundary_enable(FFRAND, 0); - if (f & FFARG) { - gotoeol(FFRAND, 1); - forwdel(FFRAND, 1); - } else { - gotobol(FFRAND, 1); - backdel(FFRAND, 1); - } - - delwhite(FFRAND, 1); - - if ((doto = curwp->w_doto) > 0) { - linsert(1, ' '); - curwp->w_doto = doto; - } - undo_boundary_enable(FFRAND, 1); - - return (TRUE); -} diff --git a/mg/re_search.c b/mg/re_search.c deleted file mode 100644 index db39fdc..0000000 --- a/mg/re_search.c +++ /dev/null @@ -1,615 +0,0 @@ -/* $OpenBSD: re_search.c,v 1.26 2011/01/21 19:10:13 kjell Exp $ */ - -/* This file is in the public domain. */ - -/* - * regular expression search commands for Mg - * - * This file contains functions to implement several of gnuemacs's regular - * expression functions for Mg. Several of the routines below are just minor - * re-arrangements of Mg's non-regular expression search functions. Some of - * them are similar in structure to the original MicroEMACS, others are - * modifications of Rich Ellison's code. Peter Newton re-wrote about half of - * them from scratch. - */ - -#ifdef REGEX -#include "def.h" - -#include -#include - -#include "macro.h" - -#define SRCH_BEGIN (0) /* search sub-codes */ -#define SRCH_FORW (-1) -#define SRCH_BACK (-2) -#define SRCH_NOPR (-3) -#define SRCH_ACCM (-4) -#define SRCH_MARK (-5) - -#define RE_NMATCH 10 /* max number of matches */ -#define REPLEN 256 /* max length of replacement string */ - -char re_pat[NPAT]; /* regex pattern */ -int re_srch_lastdir = SRCH_NOPR; /* last search flags */ -int casefoldsearch = TRUE; /* does search ignore case? */ - -static int re_doreplace(RSIZE, char *); -static int re_forwsrch(void); -static int re_backsrch(void); -static int re_readpattern(char *); -static int killmatches(int); -static int countmatches(int); - -/* - * Search forward. - * Get a search string from the user and search for it starting at ".". If - * found, move "." to just after the matched characters. display does all - * the hard stuff. If not found, it just prints a message. - */ -/* ARGSUSED */ -int -re_forwsearch(int f, int n) -{ - int s; - - if ((s = re_readpattern("RE Search")) != TRUE) - return (s); - if (re_forwsrch() == FALSE) { - ewprintf("Search failed: \"%s\"", re_pat); - return (FALSE); - } - re_srch_lastdir = SRCH_FORW; - return (TRUE); -} - -/* - * Reverse search. - * Get a search string from the user, and search, starting at "." - * and proceeding toward the front of the buffer. If found "." is left - * pointing at the first character of the pattern [the last character that - * was matched]. - */ -/* ARGSUSED */ -int -re_backsearch(int f, int n) -{ - int s; - - if ((s = re_readpattern("RE Search backward")) != TRUE) - return (s); - if (re_backsrch() == FALSE) { - ewprintf("Search failed: \"%s\"", re_pat); - return (FALSE); - } - re_srch_lastdir = SRCH_BACK; - return (TRUE); -} - -/* - * Search again, using the same search string and direction as the last search - * command. The direction has been saved in "srch_lastdir", so you know which - * way to go. - * - * XXX: This code has problems -- some incompatibility(?) with extend.c causes - * match to fail when it should not. - */ -/* ARGSUSED */ -int -re_searchagain(int f, int n) -{ - if (re_srch_lastdir == SRCH_NOPR) { - ewprintf("No last search"); - return (FALSE); - } - if (re_srch_lastdir == SRCH_FORW) { - if (re_forwsrch() == FALSE) { - ewprintf("Search failed: \"%s\"", re_pat); - return (FALSE); - } - return (TRUE); - } - if (re_srch_lastdir == SRCH_BACK) - if (re_backsrch() == FALSE) { - ewprintf("Search failed: \"%s\"", re_pat); - return (FALSE); - } - - return (TRUE); -} - -/* Compiled regex goes here-- changed only when new pattern read */ -static regex_t re_buff; -static regmatch_t re_match[RE_NMATCH]; - -/* - * Re-Query Replace. - * Replace strings selectively. Does a search and replace operation. - */ -/* 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 = re_match[0].rm_eo - re_match[0].rm_so; - if (re_doreplace((RSIZE)plen, news) == FALSE) - return (FALSE); - rcnt++; - break; - - case '.': - plen = re_match[0].rm_eo - re_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 = re_match[0].rm_eo - re_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(" replace, [.] rep-end, don't, [!] repl rest 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); -} - -/* - * Routine re_doreplace calls lreplace to make replacements needed by - * re_query replace. Its reason for existence is to deal with \1, \2. etc. - * plen: length to remove - * st: replacement string - */ -static int -re_doreplace(RSIZE plen, char *st) -{ - int j, k, s, more, num, state; - struct line *clp; - char repstr[REPLEN]; - - clp = curwp->w_dotp; - more = TRUE; - j = 0; - state = 0; - num = 0; - - /* The following FSA parses the replacement string */ - while (more) { - switch (state) { - case 0: - if (*st == '\\') { - st++; - state = 1; - } else if (*st == '\0') - more = FALSE; - else { - repstr[j] = *st; - j++; - if (j >= REPLEN) - return (FALSE); - st++; - } - break; - case 1: - if (*st >= '0' && *st <= '9') { - num = *st - '0'; - st++; - state = 2; - } else if (*st == '\0') - more = FALSE; - else { - repstr[j] = *st; - j++; - if (j >= REPLEN) - return (FALSE); - st++; - state = 0; - } - break; - case 2: - if (*st >= '0' && *st <= '9') { - num = 10 * num + *st - '0'; - st++; - } else { - if (num >= RE_NMATCH) - return (FALSE); - k = re_match[num].rm_eo - re_match[num].rm_so; - if (j + k >= REPLEN) - return (FALSE); - bcopy(&(clp->l_text[re_match[num].rm_so]), - &repstr[j], k); - j += k; - if (*st == '\0') - more = FALSE; - if (*st == '\\') { - st++; - state = 1; - } else { - repstr[j] = *st; - j++; - if (j >= REPLEN) - return (FALSE); - st++; - state = 0; - } - } - break; - } /* switch (state) */ - } /* while (more) */ - - repstr[j] = '\0'; - s = lreplace(plen, repstr); - return (s); -} - -/* - * This routine does the real work of a forward search. The pattern is - * sitting in the external variable "pat". If found, dot is updated, the - * window system is notified of the change, and TRUE is returned. If the - * string isn't found, FALSE is returned. - */ -static int -re_forwsrch(void) -{ - int tbo, error; - struct line *clp; - - clp = curwp->w_dotp; - tbo = curwp->w_doto; - - if (tbo == clp->l_used) - /* - * Don't start matching past end of line -- must move to - * beginning of next line, unless at end of file. - */ - if (clp != curbp->b_headp) { - clp = lforw(clp); - tbo = 0; - } - /* - * Note this loop does not process the last line, but this editor - * always makes the last line empty so this is good. - */ - while (clp != (curbp->b_headp)) { - re_match[0].rm_so = tbo; - re_match[0].rm_eo = llength(clp); - error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, - REG_STARTEND); - if (error != 0) { - clp = lforw(clp); - tbo = 0; - } else { - curwp->w_doto = re_match[0].rm_eo; - curwp->w_dotp = clp; - curwp->w_rflag |= WFMOVE; - return (TRUE); - } - } - return (FALSE); -} - -/* - * This routine does the real work of a backward search. The pattern is sitting - * in the external variable "re_pat". If found, dot is updated, the window - * system is notified of the change, and TRUE is returned. If the string isn't - * found, FALSE is returned. - */ -static int -re_backsrch(void) -{ - struct line *clp; - int tbo; - regmatch_t lastmatch; - - clp = curwp->w_dotp; - tbo = curwp->w_doto; - - /* Start search one position to the left of dot */ - tbo = tbo - 1; - if (tbo < 0) { - /* must move up one line */ - clp = lback(clp); - tbo = llength(clp); - } - - /* - * Note this loop does not process the last line, but this editor - * always makes the last line empty so this is good. - */ - while (clp != (curbp->b_headp)) { - re_match[0].rm_so = 0; - re_match[0].rm_eo = llength(clp); - lastmatch.rm_so = -1; - /* - * Keep searching until we don't match any longer. Assumes a - * non-match does not modify the re_match array. We have to - * do this character-by-character after the first match since - * POSIX regexps don't give you a way to do reverse matches. - */ - while (!regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, - REG_STARTEND) && re_match[0].rm_so < tbo) { - memcpy(&lastmatch, &re_match[0], sizeof(regmatch_t)); - re_match[0].rm_so++; - re_match[0].rm_eo = llength(clp); - } - if (lastmatch.rm_so == -1) { - clp = lback(clp); - tbo = llength(clp); - } else { - memcpy(&re_match[0], &lastmatch, sizeof(regmatch_t)); - curwp->w_doto = re_match[0].rm_so; - curwp->w_dotp = clp; - curwp->w_rflag |= WFMOVE; - return (TRUE); - } - } - return (FALSE); -} - -/* - * Read a pattern. - * Stash it in the external variable "re_pat". The "pat" is - * not updated if the user types in an empty line. If the user typed - * an empty line, and there is no old pattern, it is an error. - * Display the old pattern, in the style of Jeff Lomicka. There is - * some do-it-yourself control expansion. - */ -static int -re_readpattern(char *prompt) -{ - static int dofree = 0; - int flags, error, s; - char tpat[NPAT], *rep; - - if (re_pat[0] == '\0') - rep = eread("%s: ", tpat, NPAT, EFNEW | EFCR, prompt); - else - rep = eread("%s: (default %s) ", tpat, NPAT, - EFNUL | EFNEW | EFCR, prompt, re_pat); - if (rep == NULL) - return (ABORT); - if (rep[0] != '\0') { - /* New pattern given */ - (void)strlcpy(re_pat, tpat, sizeof(re_pat)); - if (casefoldsearch) - flags = REG_EXTENDED | REG_ICASE; - else - flags = REG_EXTENDED; - if (dofree) - regfree(&re_buff); - error = regcomp(&re_buff, re_pat, flags); - if (error != 0) { - char message[256]; - regerror(error, &re_buff, message, sizeof(message)); - ewprintf("Regex Error: %s", message); - re_pat[0] = '\0'; - return (FALSE); - } - dofree = 1; - s = TRUE; - } else if (rep[0] == '\0' && re_pat[0] != '\0') - /* Just using old pattern */ - s = TRUE; - else - s = FALSE; - return (s); -} - -/* - * Cause case to not matter in searches. This is the default. If called - * with argument cause case to matter. - */ -/* ARGSUSED*/ -int -setcasefold(int f, int n) -{ - if (f & FFARG) { - casefoldsearch = FALSE; - ewprintf("Case-fold-search unset"); - } else { - casefoldsearch = TRUE; - ewprintf("Case-fold-search set"); - } - - /* - * Invalidate the regular expression pattern since I'm too lazy to - * recompile it. - */ - re_pat[0] = '\0'; - return (TRUE); -} - -/* - * Delete all lines after dot that contain a string matching regex. - */ -/* ARGSUSED */ -int -delmatchlines(int f, int n) -{ - int s; - - if ((s = re_readpattern("Flush lines (containing match for regexp)")) - != TRUE) - return (s); - - s = killmatches(TRUE); - return (s); -} - -/* - * Delete all lines after dot that don't contain a string matching regex. - */ -/* ARGSUSED */ -int -delnonmatchlines(int f, int n) -{ - int s; - - if ((s = re_readpattern("Keep lines (containing match for regexp)")) - != TRUE) - return (s); - - s = killmatches(FALSE); - return (s); -} - -/* - * This function does the work of deleting matching lines. - */ -static int -killmatches(int cond) -{ - int s, error; - int count = 0; - struct line *clp; - - clp = curwp->w_dotp; - if (curwp->w_doto == llength(clp)) - /* Consider dot on next line */ - clp = lforw(clp); - - while (clp != (curbp->b_headp)) { - /* see if line matches */ - re_match[0].rm_so = 0; - re_match[0].rm_eo = llength(clp); - error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, - REG_STARTEND); - - /* Delete line when appropriate */ - if ((cond == FALSE && error) || (cond == TRUE && !error)) { - curwp->w_doto = 0; - curwp->w_dotp = clp; - count++; - s = ldelete(llength(clp) + 1, KNONE); - clp = curwp->w_dotp; - curwp->w_rflag |= WFMOVE; - if (s == FALSE) - return (FALSE); - } else - clp = lforw(clp); - } - - ewprintf("%d line(s) deleted", count); - if (count > 0) - curwp->w_rflag |= WFMOVE; - - return (TRUE); -} - -/* - * Count lines matching regex. - */ -/* ARGSUSED */ -int -cntmatchlines(int f, int n) -{ - int s; - - if ((s = re_readpattern("Count lines (matching regexp)")) != TRUE) - return (s); - s = countmatches(TRUE); - - return (s); -} - -/* - * Count lines that fail to match regex. - */ -/* ARGSUSED */ -int -cntnonmatchlines(int f, int n) -{ - int s; - - if ((s = re_readpattern("Count lines (not matching regexp)")) != TRUE) - return (s); - s = countmatches(FALSE); - - return (s); -} - -/* - * This function does the work of counting matching lines. - */ -int -countmatches(int cond) -{ - int error; - int count = 0; - struct line *clp; - - clp = curwp->w_dotp; - if (curwp->w_doto == llength(clp)) - /* Consider dot on next line */ - clp = lforw(clp); - - while (clp != (curbp->b_headp)) { - /* see if line matches */ - re_match[0].rm_so = 0; - re_match[0].rm_eo = llength(clp); - error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, - REG_STARTEND); - - /* Count line when appropriate */ - if ((cond == FALSE && error) || (cond == TRUE && !error)) - count++; - clp = lforw(clp); - } - - if (cond) - ewprintf("Number of lines matching: %d", count); - else - ewprintf("Number of lines not matching: %d", count); - - return (TRUE); -} -#endif /* REGEX */ diff --git a/mg/region.c b/mg/region.c deleted file mode 100644 index baca932..0000000 --- a/mg/region.c +++ /dev/null @@ -1,597 +0,0 @@ -/* $OpenBSD: region.c,v 1.30 2012/04/11 17:51:10 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Region based commands. - * The routines in this file deal with the region, that magic space between - * "." and mark. Some functions are commands. Some functions are just for - * internal use. - */ - -#include -#include - -#include -#include -#include -#include - -#include "def.h" - -#define TIMEOUT 10000 - -static char leftover[BUFSIZ]; - -static int getregion(struct region *); -static int iomux(int); -static int pipeio(const char *); -static int preadin(int, struct buffer *); -static void pwriteout(int, char **, int *); -static int setsize(struct region *, RSIZE); - -/* - * Kill the region. Ask "getregion" to figure out the bounds of the region. - * Move "." to the start, and kill the characters. Mark is cleared afterwards. - */ -/* ARGSUSED */ -int -killregion(int f, int n) -{ - int s; - struct region region; - - if ((s = getregion(®ion)) != TRUE) - return (s); - /* This is a kill-type command, so do magic kill buffer stuff. */ - if ((lastflag & CFKILL) == 0) - kdelete(); - thisflag |= CFKILL; - curwp->w_dotp = region.r_linep; - curwp->w_doto = region.r_offset; - curwp->w_dotline = region.r_lineno; - s = ldelete(region.r_size, KFORW | KREG); - clearmark(FFARG, 0); - - return (s); -} - -/* - * Copy all of the characters in the region to the kill buffer, - * clearing the mark afterwards. - * This is a bit like a kill region followed by a yank. - */ -/* ARGSUSED */ -int -copyregion(int f, int n) -{ - struct line *linep; - struct region region; - int loffs; - int s; - - if ((s = getregion(®ion)) != TRUE) - return (s); - - /* kill type command */ - if ((lastflag & CFKILL) == 0) - kdelete(); - thisflag |= CFKILL; - - /* current line */ - linep = region.r_linep; - - /* current offset */ - loffs = region.r_offset; - - while (region.r_size--) { - if (loffs == llength(linep)) { /* End of line. */ - if ((s = kinsert('\n', KFORW)) != TRUE) - return (s); - linep = lforw(linep); - loffs = 0; - } else { /* Middle of line. */ - if ((s = kinsert(lgetc(linep, loffs), KFORW)) != TRUE) - return (s); - ++loffs; - } - } - clearmark(FFARG, 0); - - return (TRUE); -} - -/* - * Lower case region. Zap all of the upper case characters in the region to - * lower case. Use the region code to set the limits. Scan the buffer, doing - * the changes. Call "lchange" to ensure that redisplay is done in all - * buffers. - */ -/* ARGSUSED */ -int -lowerregion(int f, int n) -{ - struct line *linep; - struct region region; - int loffs, c, s; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read-only"); - return (FALSE); - } - - if ((s = getregion(®ion)) != TRUE) - return (s); - - undo_add_change(region.r_linep, region.r_offset, region.r_size); - - lchange(WFFULL); - linep = region.r_linep; - loffs = region.r_offset; - while (region.r_size--) { - if (loffs == llength(linep)) { - linep = lforw(linep); - loffs = 0; - } else { - c = lgetc(linep, loffs); - if (ISUPPER(c) != FALSE) - lputc(linep, loffs, TOLOWER(c)); - ++loffs; - } - } - return (TRUE); -} - -/* - * Upper case region. Zap all of the lower case characters in the region to - * upper case. Use the region code to set the limits. Scan the buffer, - * doing the changes. Call "lchange" to ensure that redisplay is done in all - * buffers. - */ -/* ARGSUSED */ -int -upperregion(int f, int n) -{ - struct line *linep; - struct region region; - int loffs, c, s; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read-only"); - return (FALSE); - } - if ((s = getregion(®ion)) != TRUE) - return (s); - - undo_add_change(region.r_linep, region.r_offset, region.r_size); - - lchange(WFFULL); - linep = region.r_linep; - loffs = region.r_offset; - while (region.r_size--) { - if (loffs == llength(linep)) { - linep = lforw(linep); - loffs = 0; - } else { - c = lgetc(linep, loffs); - if (ISLOWER(c) != FALSE) - lputc(linep, loffs, TOUPPER(c)); - ++loffs; - } - } - return (TRUE); -} - -/* - * This routine figures out the bound of the region in the current window, - * and stores the results into the fields of the REGION structure. Dot and - * mark are usually close together, but I don't know the order, so I scan - * outward from dot, in both directions, looking for mark. The size is kept - * in a long. At the end, after the size is figured out, it is assigned to - * the size field of the region structure. If this assignment loses any bits, - * then we print an error. This is "type independent" overflow checking. All - * of the callers of this routine should be ready to get an ABORT status, - * because I might add a "if regions is big, ask before clobbering" flag. - */ -static int -getregion(struct region *rp) -{ - struct line *flp, *blp; - long fsize, bsize; - - if (curwp->w_markp == NULL) { - ewprintf("No mark set in this window"); - return (FALSE); - } - - /* "r_size" always ok */ - if (curwp->w_dotp == curwp->w_markp) { - rp->r_linep = curwp->w_dotp; - rp->r_lineno = curwp->w_dotline; - if (curwp->w_doto < curwp->w_marko) { - rp->r_offset = curwp->w_doto; - rp->r_size = (RSIZE)(curwp->w_marko - curwp->w_doto); - } else { - rp->r_offset = curwp->w_marko; - rp->r_size = (RSIZE)(curwp->w_doto - curwp->w_marko); - } - return (TRUE); - } - /* get region size */ - flp = blp = curwp->w_dotp; - bsize = curwp->w_doto; - fsize = llength(flp) - curwp->w_doto + 1; - while (lforw(flp) != curbp->b_headp || lback(blp) != curbp->b_headp) { - if (lforw(flp) != curbp->b_headp) { - flp = lforw(flp); - if (flp == curwp->w_markp) { - rp->r_linep = curwp->w_dotp; - rp->r_offset = curwp->w_doto; - rp->r_lineno = curwp->w_dotline; - return (setsize(rp, - (RSIZE)(fsize + curwp->w_marko))); - } - fsize += llength(flp) + 1; - } - if (lback(blp) != curbp->b_headp) { - blp = lback(blp); - bsize += llength(blp) + 1; - if (blp == curwp->w_markp) { - rp->r_linep = blp; - rp->r_offset = curwp->w_marko; - rp->r_lineno = curwp->w_markline; - return (setsize(rp, - (RSIZE)(bsize - curwp->w_marko))); - } - } - } - ewprintf("Bug: lost mark"); - return (FALSE); -} - -/* - * Set size, and check for overflow. - */ -static int -setsize(struct region *rp, RSIZE size) -{ - rp->r_size = size; - if (rp->r_size != size) { - ewprintf("Region is too large"); - return (FALSE); - } - return (TRUE); -} - -#define PREFIXLENGTH 40 -static char prefix_string[PREFIXLENGTH] = {'>', '\0'}; - -/* - * Prefix the region with whatever is in prefix_string. Leaves dot at the - * beginning of the line after the end of the region. If an argument is - * given, prompts for the line prefix string. - */ -/* ARGSUSED */ -int -prefixregion(int f, int n) -{ - struct line *first, *last; - struct region region; - char *prefix = prefix_string; - int nline; - int s; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read-only"); - return (FALSE); - } - if ((f == TRUE) && ((s = setprefix(FFRAND, 1)) != TRUE)) - return (s); - - /* get # of lines to affect */ - if ((s = getregion(®ion)) != TRUE) - return (s); - first = region.r_linep; - last = (first == curwp->w_dotp) ? curwp->w_markp : curwp->w_dotp; - for (nline = 1; first != last; nline++) - first = lforw(first); - - /* move to beginning of region */ - curwp->w_dotp = region.r_linep; - curwp->w_doto = region.r_offset; - curwp->w_dotline = region.r_lineno; - - /* for each line, go to beginning and insert the prefix string */ - while (nline--) { - (void)gotobol(FFRAND, 1); - for (prefix = prefix_string; *prefix; prefix++) - (void)linsert(1, *prefix); - (void)forwline(FFRAND, 1); - } - (void)gotobol(FFRAND, 1); - return (TRUE); -} - -/* - * Set line prefix string. Used by prefixregion. - */ -/* ARGSUSED */ -int -setprefix(int f, int n) -{ - char buf[PREFIXLENGTH], *rep; - int retval; - - if (prefix_string[0] == '\0') - rep = eread("Prefix string: ", buf, sizeof(buf), - EFNEW | EFCR); - else - rep = eread("Prefix string (default %s): ", buf, sizeof(buf), - EFNUL | EFNEW | EFCR, prefix_string); - if (rep == NULL) - return (ABORT); - if (rep[0] != '\0') { - (void)strlcpy(prefix_string, rep, sizeof(prefix_string)); - retval = TRUE; - } else if (rep[0] == '\0' && prefix_string[0] != '\0') { - /* CR -- use old one */ - retval = TRUE; - } else - retval = FALSE; - return (retval); -} - -int -region_get_data(struct region *reg, char *buf, int len) -{ - int i, off; - struct line *lp; - - off = reg->r_offset; - lp = reg->r_linep; - for (i = 0; i < len; i++) { - if (off == llength(lp)) { - lp = lforw(lp); - if (lp == curbp->b_headp) - break; - off = 0; - buf[i] = '\n'; - } else { - buf[i] = lgetc(lp, off); - off++; - } - } - buf[i] = '\0'; - return (i); -} - -void -region_put_data(const char *buf, int len) -{ - int i; - - for (i = 0; buf[i] != '\0' && i < len; i++) { - if (buf[i] == '\n') - lnewline(); - else - linsert(1, buf[i]); - } -} - -/* - * Mark whole buffer by first traversing to end-of-buffer - * and then to beginning-of-buffer. Mark, dot are implicitly - * set to eob, bob respectively during traversal. - */ -int -markbuffer(int f, int n) -{ - if (gotoeob(f,n) == FALSE) - return (FALSE); - if (gotobob(f,n) == FALSE) - return (FALSE); - return (TRUE); -} - -/* - * Pipe text from current region to external command. - */ -/*ARGSUSED */ -int -piperegion(int f, int n) -{ - char *cmd, cmdbuf[NFILEN]; - - /* C-u M-| is not supported yet */ - if (n > 1) - return (ABORT); - - if (curwp->w_markp == NULL) { - ewprintf("The mark is not set now, so there is no region"); - return (FALSE); - } - if ((cmd = eread("Shell command on region: ", cmdbuf, sizeof(cmdbuf), - EFNEW | EFCR)) == NULL || (cmd[0] == '\0')) - return (ABORT); - - return (pipeio(cmdbuf)); -} - -/* - * Create a socketpair, fork and execl cmd passed. STDIN, STDOUT - * and STDERR of child process are redirected to socket. - */ -int -pipeio(const char* const cmd) -{ - int s[2]; - char *shellp; - - if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s) == -1) { - ewprintf("socketpair error"); - return (FALSE); - } - switch(fork()) { - case -1: - ewprintf("Can't fork"); - return (FALSE); - case 0: - /* Child process */ - close(s[0]); - if (dup2(s[1], STDIN_FILENO) == -1) - _exit(1); - if (dup2(s[1], STDOUT_FILENO) == -1) - _exit(1); - if (dup2(s[1], STDERR_FILENO) == -1) - _exit(1); - if ((shellp = getenv("SHELL")) == NULL) - _exit(1); - execl(shellp, "sh", "-c", cmd, (char *)NULL); - _exit(1); - default: - /* Parent process */ - close(s[1]); - return iomux(s[0]); - } - return (FALSE); -} - -/* - * Multiplex read, write on socket fd passed. First get the region, - * find/create *Shell Command Output* buffer and clear it's contents. - * Poll on the fd for both read and write readiness. - */ -int -iomux(int fd) -{ - struct region region; - struct buffer *bp; - struct pollfd pfd[1]; - int nfds; - char *text, *textcopy; - - if (getregion(®ion) != TRUE) - return (FALSE); - - if ((text = malloc(region.r_size + 1)) == NULL) - return (ABORT); - - region_get_data(®ion, text, region.r_size); - textcopy = text; - fcntl(fd, F_SETFL, O_NONBLOCK); - - /* There is nothing to write if r_size is zero - * but the cmd's output should be read so shutdown - * the socket for writing only. - */ - if (region.r_size == 0) - shutdown(fd, SHUT_WR); - - bp = bfind("*Shell Command Output*", TRUE); - bp->b_flag |= BFREADONLY; - if (bclear(bp) != TRUE) - return (FALSE); - - pfd[0].fd = fd; - pfd[0].events = POLLIN | POLLOUT; - while ((nfds = poll(pfd, 1, TIMEOUT)) != -1 || - (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))) { - if (pfd[0].revents & POLLOUT && region.r_size > 0) - pwriteout(fd, &textcopy, ®ion.r_size); - else if (pfd[0].revents & POLLIN) - if (preadin(fd, bp) == FALSE) - break; - } - close(fd); - free(text); - /* In case if last line doesn't have a '\n' add the leftover - * characters to buffer. - */ - if (leftover[0] != '\0') { - addline(bp, leftover); - leftover[0] = '\0'; - } - if (nfds == 0) { - ewprintf("poll timed out"); - return (FALSE); - } else if (nfds == -1) { - ewprintf("poll error"); - return (FALSE); - } - return (popbuftop(bp, WNONE)); -} - -/* - * Write some text from region to fd. Once done shutdown the - * write end. - */ -void -pwriteout(int fd, char **text, int *len) -{ - int w; - - if (((w = send(fd, *text, *len, MSG_NOSIGNAL)) == -1)) { - switch(errno) { - case EPIPE: - *len = -1; - break; - case EAGAIN: - return; - } - } else - *len -= w; - - *text += w; - if (*len <= 0) - shutdown(fd, SHUT_WR); -} - -/* - * Read some data from socket fd, break on '\n' and add - * to buffer. If couldn't break on newline hold leftover - * characters and append in next iteration. - */ -int -preadin(int fd, struct buffer *bp) -{ - int len; - static int nooutput; - char buf[BUFSIZ], *p, *q; - - if ((len = read(fd, buf, BUFSIZ - 1)) == 0) { - if (nooutput == 0) - addline(bp, "(Shell command succeeded with no output)"); - nooutput = 0; - return (FALSE); - } - nooutput = 1; - buf[len] = '\0'; - p = q = buf; - if (leftover[0] != '\0' && ((q = strchr(p, '\n')) != NULL)) { - *q++ = '\0'; - if (strlcat(leftover, p, sizeof(leftover)) >= - sizeof(leftover)) { - ewprintf("line too long"); - return (FALSE); - } - addline(bp, leftover); - leftover[0] = '\0'; - p = q; - } - while ((q = strchr(p, '\n')) != NULL) { - *q++ = '\0'; - addline(bp, p); - p = q; - } - if (strlcpy(leftover, p, sizeof(leftover)) >= sizeof(leftover)) { - ewprintf("line too long"); - return (FALSE); - } - return (TRUE); -} diff --git a/mg/spawn.c b/mg/spawn.c deleted file mode 100644 index 13fd985..0000000 --- a/mg/spawn.c +++ /dev/null @@ -1,48 +0,0 @@ -/* $OpenBSD: spawn.c,v 1.11 2006/08/01 22:16:03 jason Exp $ */ - -/* This file is in the public domain. */ - -/* - * Spawn. Actually just suspends Mg. - * Assumes POSIX job control. - */ - -#include "def.h" - -#include -#include - -/* - * This causes mg to send itself a stop signal. It assumes the parent - * shell supports POSIX job control. If the terminal supports an alternate - * screen, we will switch to it. - */ -/* ARGSUSED */ -int -spawncli(int f, int n) -{ - sigset_t oset; - - /* Very similar to what vttidy() does. */ - ttcolor(CTEXT); - ttnowindow(); - ttmove(nrow - 1, 0); - if (epresf != FALSE) { - tteeol(); - epresf = FALSE; - } - if (ttcooked() == FALSE) - return (FALSE); - - /* Exit application mode and tidy. */ - tttidy(); - ttflush(); - (void)sigprocmask(SIG_SETMASK, NULL, &oset); - (void)kill(0, SIGTSTP); - (void)sigprocmask(SIG_SETMASK, &oset, NULL); - ttreinit(); - - /* Force repaint. */ - sgarbf = TRUE; - return (ttraw()); -} diff --git a/mg/sysdef.h b/mg/sysdef.h deleted file mode 100644 index 6b75614..0000000 --- a/mg/sysdef.h +++ /dev/null @@ -1,30 +0,0 @@ -/* $OpenBSD: sysdef.h,v 1.16 2008/09/15 16:11:35 kjell Exp $ */ - -/* This file is in the public domain. */ - -/* - * POSIX system header file - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#define KBLOCK 8192 /* Kill grow. */ -#define GOOD 0 /* Good exit status. */ - -typedef int RSIZE; /* Type for file/region sizes */ -typedef short KCHAR; /* Type for internal keystrokes */ - -#define MALLOCROUND(m) (m+=7,m&=~7) /* round up to 8 byte boundary */ - -struct fileinfo { - uid_t fi_uid; - gid_t fi_gid; - mode_t fi_mode; - struct timespec fi_mtime; /* Last modified time */ -}; diff --git a/mg/tags.c b/mg/tags.c deleted file mode 100644 index 92d1425..0000000 --- a/mg/tags.c +++ /dev/null @@ -1,533 +0,0 @@ -/* $OpenBSD: tags.c,v 1.5 2012/07/02 08:08:31 lum Exp $ */ - -/* - * This file is in the public domain. - * - * Author: Sunil Nimmagadda - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "def.h" - -struct ctag; - -static int addctag(char *); -static int atbow(void); -void closetags(void); -static int ctagcmp(struct ctag *, struct ctag *); -static int loadbuffer(char *); -static int loadtags(const char *); -static int pushtag(char *); -static int searchpat(char *); -static struct ctag *searchtag(char *); -static char *strip(char *, size_t); -static void unloadtags(void); - -#define DEFAULTFN "tags" - -char *tagsfn = NULL; -int loaded = FALSE; - -/* ctags(1) entries are parsed and maintained in a tree. */ -struct ctag { - RB_ENTRY(ctag) entry; - char *tag; - char *fname; - char *pat; -}; -RB_HEAD(tagtree, ctag) tags = RB_INITIALIZER(&tags); -RB_GENERATE(tagtree, ctag, entry, ctagcmp); - -struct tagpos { - SLIST_ENTRY(tagpos) entry; - int doto; - int dotline; - char *bname; -}; -SLIST_HEAD(tagstack, tagpos) shead = SLIST_HEAD_INITIALIZER(shead); - -int -ctagcmp(struct ctag *s, struct ctag *t) -{ - return strcmp(s->tag, t->tag); -} - -/* - * Record the filename that contain tags to be used while loading them - * on first use. If a filename is already recorded, ask user to retain - * already loaded tags (if any) and unload them if user chooses not to. - */ -/* ARGSUSED */ -int -tagsvisit(int f, int n) -{ - char fname[NFILEN], *bufp, *temp; - struct stat sb; - - if (getbufcwd(fname, sizeof(fname)) == FALSE) - fname[0] = '\0'; - - if (strlcat(fname, DEFAULTFN, sizeof(fname)) >= sizeof(fname)) { - ewprintf("Filename too long"); - return (FALSE); - } - - bufp = eread("visit tags table (default %s): ", fname, - NFILEN, EFFILE | EFCR | EFNEW | EFDEF, DEFAULTFN); - - if (stat(bufp, &sb) == -1) { - ewprintf("stat: %s", strerror(errno)); - return (FALSE); - } else if (S_ISREG(sb.st_mode) == 0) { - ewprintf("Not a regular file"); - return (FALSE); - } else if (access(bufp, R_OK) == -1) { - ewprintf("Cannot access file %s", bufp); - return (FALSE); - } - - if (tagsfn == NULL) { - if (bufp == NULL) - return (ABORT); - else if (bufp[0] == '\0') { - if ((tagsfn = strdup(fname)) == NULL) { - ewprintf("Out of memory"); - return (FALSE); - } - } else { - /* bufp points to local variable, so duplicate. */ - if ((tagsfn = strdup(bufp)) == NULL) { - ewprintf("Out of memory"); - return (FALSE); - } - } - } else { - if ((temp = strdup(bufp)) == NULL) { - ewprintf("Out of memory"); - return (FALSE); - } - free(tagsfn); - tagsfn = temp; - if (eyorn("Keep current list of tags table also") == FALSE) { - ewprintf("Starting a new list of tags table"); - unloadtags(); - } - loaded = FALSE; - } - return (TRUE); -} - -/* - * Ask user for a tag while treating word at dot as default. Visit tags - * file if not yet done, load tags and jump to definition of the tag. - */ -int -findtag(int f, int n) -{ - char utok[MAX_TOKEN], dtok[MAX_TOKEN]; - char *tok, *bufp; - int ret; - - if (curtoken(f, n, dtok) == FALSE) - return (FALSE); - - bufp = eread("Find tag (default %s) ", utok, MAX_TOKEN, - EFNUL | EFNEW, dtok); - - if (bufp == NULL) - return (ABORT); - else if (bufp[0] == '\0') - tok = dtok; - else - tok = utok; - - if (tok[0] == '\0') { - ewprintf("There is no default tag"); - return (FALSE); - } - - if (tagsfn == NULL) - if ((ret = tagsvisit(f, n)) != TRUE) - return (ret); - if (!loaded) { - if (loadtags(tagsfn) == FALSE) { - free(tagsfn); - tagsfn = NULL; - return (FALSE); - } - loaded = TRUE; - } - return pushtag(tok); -} - -/* - * Free tags tree. - */ -void -unloadtags(void) -{ - struct ctag *var, *nxt; - - for (var = RB_MIN(tagtree, &tags); var != NULL; var = nxt) { - nxt = RB_NEXT(tagtree, &tags, var); - RB_REMOVE(tagtree, &tags, var); - /* line parsed with fparseln needs to be freed */ - free(var->tag); - free(var); - } -} - -/* - * Lookup tag passed in tree and if found, push current location and - * buffername onto stack, load the file with tag definition into a new - * buffer and position dot at the pattern. - */ -/*ARGSUSED */ -int -pushtag(char *tok) -{ - struct ctag *res; - struct tagpos *s; - char bname[NFILEN]; - int doto, dotline; - - if ((res = searchtag(tok)) == NULL) - return (FALSE); - - doto = curwp->w_doto; - dotline = curwp->w_dotline; - /* record absolute filenames. Fixes issues when mg's cwd is not the - * same as buffer's directory. - */ - if (strlcpy(bname, curbp->b_cwd, sizeof(bname)) >= sizeof(bname)) { - ewprintf("filename too long"); - return (FALSE); - } - if (strlcat(bname, curbp->b_bname, sizeof(bname)) >= sizeof(bname)) { - ewprintf("filename too long"); - return (FALSE); - } - - if (loadbuffer(res->fname) == FALSE) - return (FALSE); - - if (searchpat(res->pat) == TRUE) { - if ((s = malloc(sizeof(struct tagpos))) == NULL) { - ewprintf("Out of memory"); - return (FALSE); - } - if ((s->bname = strdup(bname)) == NULL) { - ewprintf("Out of memory"); - return (FALSE); - } - s->doto = doto; - s->dotline = dotline; - SLIST_INSERT_HEAD(&shead, s, entry); - return (TRUE); - } else { - ewprintf("%s: pattern not found", res->tag); - return (FALSE); - } - /* NOTREACHED */ - return (FALSE); -} - -/* - * If tag stack is not empty pop stack and jump to recorded buffer, dot. - */ -/* ARGSUSED */ -int -poptag(int f, int n) -{ - struct line *dotp; - struct tagpos *s; - - if (SLIST_EMPTY(&shead)) { - ewprintf("No previous location for find-tag invocation"); - return (FALSE); - } - s = SLIST_FIRST(&shead); - SLIST_REMOVE_HEAD(&shead, entry); - if (loadbuffer(s->bname) == FALSE) - return (FALSE); - curwp->w_dotline = s->dotline; - curwp->w_doto = s->doto; - - /* storing of dotp in tagpos wouldn't work out in cases when - * that buffer is killed by user(dangling pointer). Explicitly - * traverse till dotline for correct handling. - */ - dotp = curwp->w_bufp->b_headp; - while (s->dotline--) - dotp = dotp->l_fp; - - curwp->w_dotp = dotp; - free(s->bname); - free(s); - return (TRUE); -} - -/* - * Parse the tags file and construct the tags tree. Remove escape - * characters while parsing the file. - */ -int -loadtags(const char *fn) -{ - char *l; - FILE *fd; - - if ((fd = fopen(fn, "r")) == NULL) { - ewprintf("Unable to open tags file: %s", fn); - return (FALSE); - } - while ((l = fparseln(fd, NULL, NULL, "\\\\\0", - FPARSELN_UNESCCONT | FPARSELN_UNESCREST)) != NULL) { - if (addctag(l) == FALSE) { - fclose(fd); - return (FALSE); - } - } - fclose(fd); - return (TRUE); -} - -/* - * Cleanup and destroy tree and stack. - */ -void -closetags(void) -{ - struct tagpos *s; - - while (!SLIST_EMPTY(&shead)) { - s = SLIST_FIRST(&shead); - SLIST_REMOVE_HEAD(&shead, entry); - free(s->bname); - free(s); - } - unloadtags(); - free(tagsfn); -} - -/* - * Strip away any special characters in pattern. - * The pattern in ctags isn't a true regular expression. Its of the form - * /^xxx$/ or ?^xxx$? and in some cases the "$" would be missing. Strip - * the leading and trailing special characters so the pattern matching - * would be a simple string compare. Escape character is taken care by - * fparseln. - */ -char * -strip(char *s, size_t len) -{ - /* first strip trailing special chars */ - s[len - 1] = '\0'; - if (s[len - 2] == '$') - s[len - 2] = '\0'; - - /* then strip leading special chars */ - s++; - if (*s == '^') - s++; - - return s; -} - -/* - * tags line is of the format "\t\t". Split them - * by replacing '\t' with '\0'. This wouldn't alter the size of malloc'ed - * l, and can be freed during cleanup. - */ -int -addctag(char *l) -{ - struct ctag *t; - - if ((t = malloc(sizeof(struct ctag))) == NULL) { - ewprintf("Out of memory"); - return (FALSE); - } - t->tag = l; - if ((l = strchr(l, '\t')) == NULL) - goto cleanup; - *l++ = '\0'; - t->fname = l; - if ((l = strchr(l, '\t')) == NULL) - goto cleanup; - *l++ = '\0'; - if (*l == '\0') - goto cleanup; - t->pat = strip(l, strlen(l)); - RB_INSERT(tagtree, &tags, t); - return (TRUE); -cleanup: - free(t); - free(l); - return (TRUE); -} - -/* - * Search through each line of buffer for pattern. - */ -int -searchpat(char *pat) -{ - struct line *lp; - int dotline; - size_t plen; - - plen = strlen(pat); - dotline = 1; - lp = lforw(curbp->b_headp); - while (lp != curbp->b_headp) { - if (ltext(lp) != NULL && plen <= llength(lp) && - (strncmp(pat, ltext(lp), plen) == 0)) { - curwp->w_doto = 0; - curwp->w_dotp = lp; - curwp->w_dotline = dotline; - return (TRUE); - } else { - lp = lforw(lp); - dotline++; - } - } - return (FALSE); -} - -/* - * Return TRUE if dot is at beginning of a word or at beginning - * of line, else FALSE. - */ -int -atbow(void) -{ - if (curwp->w_doto == 0) - return (TRUE); - if (ISWORD(curwp->w_dotp->l_text[curwp->w_doto]) && - !ISWORD(curwp->w_dotp->l_text[curwp->w_doto - 1])) - return (TRUE); - return (FALSE); -} - -/* - * Extract the word at dot without changing dot position. - */ -int -curtoken(int f, int n, char *token) -{ - struct line *odotp; - int odoto, tdoto, odotline, size, r; - char c; - - /* Underscore character is to be treated as "inword" while - * processing tokens unlike mg's default word traversal. Save - * and restore it's cinfo value so that tag matching works for - * identifier with underscore. - */ - c = cinfo['_']; - cinfo['_'] = _MG_W; - - odotp = curwp->w_dotp; - odoto = curwp->w_doto; - odotline = curwp->w_dotline; - - /* Move backword unless we are at the beginning of a word or at - * beginning of line. - */ - if (!atbow()) - if ((r = backword(f, n)) == FALSE) - goto cleanup; - - tdoto = curwp->w_doto; - - if ((r = forwword(f, n)) == FALSE) - goto cleanup; - - /* strip away leading whitespace if any like emacs. */ - while (ltext(curwp->w_dotp) && - isspace(curwp->w_dotp->l_text[tdoto])) - tdoto++; - - size = curwp->w_doto - tdoto; - if (size <= 0 || size >= MAX_TOKEN || - ltext(curwp->w_dotp) == NULL) { - r = FALSE; - goto cleanup; - } - strncpy(token, ltext(curwp->w_dotp) + tdoto, size); - token[size] = '\0'; - r = TRUE; - -cleanup: - cinfo['_'] = c; - curwp->w_dotp = odotp; - curwp->w_doto = odoto; - curwp->w_dotline = odotline; - return (r); -} - -/* - * Search tagstree for a given token. - */ -struct ctag * -searchtag(char *tok) -{ - struct ctag t, *res; - - t.tag = tok; - if ((res = RB_FIND(tagtree, &tags, &t)) == NULL) { - ewprintf("No tag containing %s", tok); - return (NULL); - } - return res; -} - -/* - * This is equivalent to filevisit from file.c. - * Look around to see if we can find the file in another buffer; if we - * can't find it, create a new buffer, read in the text, and switch to - * the new buffer. *scratch*, *grep*, *compile* needs to be handled - * differently from other buffers which have "filenames". - */ -int -loadbuffer(char *bname) -{ - struct buffer *bufp; - char *adjf; - - /* check for special buffers which begin with '*' */ - if (bname[0] == '*') { - if ((bufp = bfind(bname, FALSE)) != NULL) { - curbp = bufp; - return (showbuffer(bufp, curwp, WFFULL)); - } else { - return (FALSE); - } - } else { - if ((adjf = adjustname(bname, TRUE)) == NULL) - return (FALSE); - if ((bufp = findbuffer(adjf)) == NULL) - return (FALSE); - } - curbp = bufp; - if (showbuffer(bufp, curwp, WFFULL) != TRUE) - return (FALSE); - if (bufp->b_fname[0] == '\0') { - if (readin(adjf) != TRUE) { - killbuffer(bufp); - return (FALSE); - } - } - return (TRUE); -} diff --git a/mg/theo.c b/mg/theo.c deleted file mode 100644 index 408f9e1..0000000 --- a/mg/theo.c +++ /dev/null @@ -1,192 +0,0 @@ -/* $OpenBSD: theo.c,v 1.124 2012/07/09 22:24:36 mlarkin Exp $ */ -/* - * Copyright (c) 2002 Artur Grabowski - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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 "def.h" -#include "kbd.h" -#include "funmap.h" - -void theo_init(void); -static int theo_analyze(int, int); -static int theo(int, int); - -static PF theo_pf[] = { - theo_analyze -}; - -static struct KEYMAPE (1 + IMAPEXT) theomap = { - 1, - 1 + IMAPEXT, - rescan, - { - { CCHR('M'), CCHR('M'), theo_pf, NULL } - } -}; - -void -theo_init(void) -{ - funmap_add(theo, "theo"); - maps_add((KEYMAP *)&theomap, "theo"); -} - -/* ARGSUSED */ -static int -theo(int f, int n) -{ - struct buffer *bp; - struct mgwin *wp; - - bp = bfind("theo", TRUE); - if (bclear(bp) != TRUE) - return (FALSE); - - bp->b_modes[0] = name_mode("fundamental"); - bp->b_modes[1] = name_mode("theo"); - bp->b_nmodes = 1; - - if ((wp = popbuf(bp, WNONE)) == NULL) - return (FALSE); - - curbp = bp; - curwp = wp; - onlywind(f, n); - - return (TRUE); -} - -static const char *talk[] = { - "Write more code.", - "Make more commits.", - "That's because you have been slacking.", - "slacker!", - "That's what happens when you're lazy.", - "idler!", - "slackass!", - "lazy bum!", - "Stop slacking you lazy bum!", - "slacker slacker lazy bum bum bum slacker!", - "I could search... but I'm a lazy bum ;)", - "sshutup sshithead, ssharpsshooting susshi sshplats ssharking assholes.", - "Lazy bums slacking on your asses.", - "35 commits an hour? That's pathetic!", - "Fine software takes time to prepare. Give a little slack.", - "I am just stating a fact", - "you bring new meaning to the terms slackass. I will have to invent a new term.", - "if they cut you out, muddy their back yards", - "Make them want to start over, and play nice the next time.", - "It is clear that this has not been thought through.", - "avoid using abort(). it is not nice.", - "That's the most ridiculous thing I've heard in the last two or three minutes!", - "I'm not just doing this for crowd response. I need to be right.", - "I'd put a fan on my bomb.. And blinking lights...", - "I love to fight", - "No sane people allowed here. Go home.", - "you have to stop peeing on your breakfast", - "feature requests come from idiots", - "henning and darren / sitting in a tree / t o k i n g / a joint or three", - "KICK ASS. TIME FOR A JASON LOVE IN! WE CAN ALL GET LOST IN HIS HAIR!", - "shame on you for following my rules.", - "altq's parser sucks dead whale farts through the finest chemistry pipette's", - "screw this operating system shit, i just want to drive!", - "Search for fuck. Anytime you see that word, you have a paragraph to write.", - "Yes, but the ports people are into S&M.", - "Buttons are for idiots.", - "We are not hackers. We are turd polishing craftsmen.", - "who cares. style(9) can bite my ass", - "It'd be one fucking happy planet if it wasn't for what's under this fucking sticker.", - "I would explain, but I am too drunk.", - "you slackers don't deserve pictures yet", - "Vegetarian my ass", - "Wait a minute, that's a McNally's!", - "don't they recognize their moral responsibility to entertain me?", - "#ifdef is for emacs developers.", - "Many well known people become net-kooks in their later life, because they lose touch with reality.", - "You're not allowed to have an opinion.", - "tweep tweep tweep", - "Quite frankly, SSE's alignment requirement is the most utterly retarded idea since eating your own shit.", - "Holy verbose prom startup Batman.", - "Any day now, when we sell out.", - "optimism in man kind does not belong here", - "First user who tries to push this button, he pounds into the ground with a rant of death.", - "we did farts. now we do sperm. we are cutting edge.", - "the default configuration is a mixture of piss, puke, shit, and bloody entrails.", - "Stop wasting your time reading people's licenses.", - "doing it with environment variables is OH SO SYSTEM FIVE LIKE OH MY GOD PASS ME THE SPOON", - "Linux is fucking POO, not just bad, bad REALLY REALLY BAD", - "penguins are not much more than chickens that swim.", - "i am a packet sniffing fool, let me wipe my face with my own poo", - "Whiners. They scale really well.", - "in your world, you would have a checklist of 50 fucking workarounds just to make a coffee.", - "for once, I have nothing to say.", - "You have no idea how fucked we are", - "You can call it fart if you want to.", - "wavelan is a battle field", - "You are in a maze of gpio pins, all alike, all undocumented, and a few are wired to bombs.", - "And that is why humppa sucks... cause it has no cause.", - "cache aliasing is a problem that would have stopped in 1992 if someone had killed about 5 people who worked at Sun.", - "Don't spread rumours about me being gentle.", - "If municipal water filtering equipment was built by the gcc developers, the western world would be dead by now.", - "kettenis supported a new machine in my basement and all I got to do was fix a 1 character typo in his html page commit.", - "industry told us a lesson: when you're an asshole, they mail you hardware", - "I was joking, really. I think I am funny :-)", - "the kernel is a harsh mistress", - "Have I ever been subtle? If my approach ever becomes subtle, shoot me.", - "the acpi stabs you in the back. the acpi stabs you in the back. you die ...", - "My cats are more observant than you.", - "our kernels have no bugs", - "style(9) has all these fascist rules, and i have a problem with some of them because i didn't come up with them", - "I'm not very reliable", - "I don't like control", - "You aren't being conservative -- you are trying to be a caveman.", - "nfs loves everyone", - "basically, dung beetles fucking. that's what kerberosV + openssl is like", - "I would rather run Windows than use vi.", - "if you assign that responsibility to non-hikers I will walk over and cripple you now.", - "i ojbect two yoru splelng of achlhlocis.", - "We have two kinds of developers - those that deal with their own shit and those that deal with other people's shit." -}; - -static const int ntalk = sizeof(talk)/sizeof(talk[0]); - -/* ARGSUSED */ -static int -theo_analyze(int f, int n) -{ - const char *str; - int len; - - str = talk[arc4random_uniform(ntalk)]; - len = strlen(str); - - newline(FFRAND, 2); - - while (len--) - linsert(1, *str++); - - newline(FFRAND, 2); - - return (TRUE); -} diff --git a/mg/tty.c b/mg/tty.c deleted file mode 100644 index f803cc7..0000000 --- a/mg/tty.c +++ /dev/null @@ -1,447 +0,0 @@ -/* $OpenBSD: tty.c,v 1.30 2008/09/15 16:11:35 kjell Exp $ */ - -/* This file is in the public domain. */ - -/* - * Terminfo display driver - * - * Terminfo is a terminal information database and routines to describe - * terminals on most modern UNIX systems. Many other systems have adopted - * this as a reasonable way to allow for widely varying and ever changing - * varieties of terminal types. This should be used where practical. - */ -/* - * Known problems: If you have a terminal with no clear to end of screen and - * memory of lines below the ones visible on the screen, display will be - * wrong in some cases. I doubt that any such terminal was ever made, but I - * thought everyone with delete line would have clear to end of screen too... - * - * Code for terminals without clear to end of screen and/or clear to end of line - * has not been extensively tested. - * - * Cost calculations are very rough. Costs of insert/delete line may be far - * from the truth. This is accentuated by display.c not knowing about - * multi-line insert/delete. - * - * Using scrolling region vs insert/delete line should probably be based on cost - * rather than the assumption that scrolling region operations look better. - */ - -#include "def.h" - -#include -#include -#include - -#include - -static int charcost(char *); - -static int cci; -static int insdel; /* Do we have both insert & delete line? */ -static char *scroll_fwd; /* How to scroll forward. */ - -static void winchhandler(int); - -/* ARGSUSED */ -static void -winchhandler(int sig) -{ - winch_flag = 1; -} - -/* - * Initialize the terminal when the editor - * gets started up. - */ -void -ttinit(void) -{ - int errret; - - if (setupterm(NULL, 1, &errret)) - panic("Terminal setup failed"); - - signal(SIGWINCH, winchhandler); - signal(SIGCONT, winchhandler); - siginterrupt(SIGWINCH, 1); - - scroll_fwd = scroll_forward; - if (scroll_fwd == NULL || *scroll_fwd == '\0') { - /* this is what GNU Emacs does */ - scroll_fwd = parm_down_cursor; - if (scroll_fwd == NULL || *scroll_fwd == '\0') - scroll_fwd = "\n"; - } - - if (cursor_address == NULL || cursor_up == NULL) - panic("This terminal is too stupid to run mg"); - - /* set nrow & ncol */ - ttresize(); - - if (!clr_eol) - tceeol = ncol; - else - tceeol = charcost(clr_eol); - - /* Estimate cost of inserting a line */ - if (change_scroll_region && scroll_reverse) - tcinsl = charcost(change_scroll_region) * 2 + - charcost(scroll_reverse); - else if (parm_insert_line) - tcinsl = charcost(parm_insert_line); - else if (insert_line) - tcinsl = charcost(insert_line); - else - /* make this cost high enough */ - tcinsl = nrow * ncol; - - /* Estimate cost of deleting a line */ - if (change_scroll_region) - tcdell = charcost(change_scroll_region) * 2 + - charcost(scroll_fwd); - else if (parm_delete_line) - tcdell = charcost(parm_delete_line); - else if (delete_line) - tcdell = charcost(delete_line); - else - /* make this cost high enough */ - tcdell = nrow * ncol; - - /* Flag to indicate that we can both insert and delete lines */ - insdel = (insert_line || parm_insert_line) && - (delete_line || parm_delete_line); - - if (enter_ca_mode) - /* enter application mode */ - putpad(enter_ca_mode, 1); - - ttresize(); -} - -/* - * Re-initialize the terminal when the editor is resumed. - * The keypad_xmit doesn't really belong here but... - */ -void -ttreinit(void) -{ - /* check if file was modified while we were gone */ - if (fchecktime(curbp) != TRUE) { - curbp->b_flag |= BFDIRTY; - } - - if (enter_ca_mode) - /* enter application mode */ - putpad(enter_ca_mode, 1); - - if (keypad_xmit) - /* turn on keypad */ - putpad(keypad_xmit, 1); - - ttresize(); -} - -/* - * Clean up the terminal, in anticipation of a return to the command - * interpreter. This is a no-op on the ANSI display. On the SCALD display, - * it sets the window back to half screen scrolling. Perhaps it should - * query the display for the increment, and put it back to what it was. - */ -void -tttidy(void) -{ -#ifdef XKEYS - ttykeymaptidy(); -#endif /* XKEYS */ - - /* set the term back to normal mode */ - if (exit_ca_mode) - putpad(exit_ca_mode, 1); -} - -/* - * Move the cursor to the specified origin 0 row and column position. Try to - * optimize out extra moves; redisplay may have left the cursor in the right - * location last time! - */ -void -ttmove(int row, int col) -{ - if (ttrow != row || ttcol != col) { - putpad(tgoto(cursor_address, col, row), 1); - ttrow = row; - ttcol = col; - } -} - -/* - * Erase to end of line. - */ -void -tteeol(void) -{ - int i; - - if (clr_eol) - putpad(clr_eol, 1); - else { - i = ncol - ttcol; - while (i--) - ttputc(' '); - ttrow = ttcol = HUGE; - } -} - -/* - * Erase to end of page. - */ -void -tteeop(void) -{ - int line; - - if (clr_eos) - putpad(clr_eos, nrow - ttrow); - else { - putpad(clr_eol, 1); - if (insdel) - ttdell(ttrow + 1, lines, lines - ttrow - 1); - else { - /* do it by hand */ - for (line = ttrow + 1; line <= lines; ++line) { - ttmove(line, 0); - tteeol(); - } - } - ttrow = ttcol = HUGE; - } -} - -/* - * Make a noise. - */ -void -ttbeep(void) -{ - putpad(bell, 1); - ttflush(); -} - -/* - * Insert nchunk blank line(s) onto the screen, scrolling the last line on - * the screen off the bottom. Use the scrolling region if possible for a - * smoother display. If there is no scrolling region, use a set of insert - * and delete line sequences. - */ -void -ttinsl(int row, int bot, int nchunk) -{ - int i, nl; - - /* Case of one line insert is special. */ - if (row == bot) { - ttmove(row, 0); - tteeol(); - return; - } - if (change_scroll_region && scroll_reverse) { - /* Use scroll region and back index */ - nl = bot - row; - ttwindow(row, bot); - ttmove(row, 0); - while (nchunk--) - putpad(scroll_reverse, nl); - ttnowindow(); - return; - } else if (insdel) { - ttmove(1 + bot - nchunk, 0); - nl = nrow - ttrow; - if (parm_delete_line) - putpad(tgoto(parm_delete_line, 0, nchunk), nl); - else - /* For all lines in the chunk... */ - for (i = 0; i < nchunk; i++) - putpad(delete_line, nl); - ttmove(row, 0); - - /* ttmove() changes ttrow */ - nl = nrow - ttrow; - - if (parm_insert_line) - putpad(tgoto(parm_insert_line, 0, nchunk), nl); - else - /* For all lines in the chunk */ - for (i = 0; i < nchunk; i++) - putpad(insert_line, nl); - ttrow = HUGE; - ttcol = HUGE; - } else - panic("ttinsl: Can't insert/delete line"); -} - -/* - * Delete nchunk line(s) from "row", replacing the bottom line on the - * screen with a blank line. Unless we're using the scrolling region, - * this is done with crafty sequences of insert and delete lines. The - * presence of the echo area makes a boundary condition go away. - */ -void -ttdell(int row, int bot, int nchunk) -{ - int i, nl; - - /* One line special cases */ - if (row == bot) { - ttmove(row, 0); - tteeol(); - return; - } - /* scrolling region */ - if (change_scroll_region) { - nl = bot - row; - ttwindow(row, bot); - ttmove(bot, 0); - while (nchunk--) - putpad(scroll_fwd, nl); - ttnowindow(); - /* else use insert/delete line */ - } else if (insdel) { - ttmove(row, 0); - nl = nrow - ttrow; - if (parm_delete_line) - putpad(tgoto(parm_delete_line, 0, nchunk), nl); - else - /* For all lines in the chunk */ - for (i = 0; i < nchunk; i++) - putpad(delete_line, nl); - ttmove(1 + bot - nchunk, 0); - - /* ttmove() changes ttrow */ - nl = nrow - ttrow; - if (parm_insert_line) - putpad(tgoto(parm_insert_line, 0, nchunk), nl); - else - /* For all lines in the chunk */ - for (i = 0; i < nchunk; i++) - putpad(insert_line, nl); - ttrow = HUGE; - ttcol = HUGE; - } else - panic("ttdell: Can't insert/delete line"); -} - -/* - * This routine sets the scrolling window on the display to go from line - * "top" to line "bot" (origin 0, inclusive). The caller checks for the - * pathological 1-line scroll window which doesn't work right and avoids - * it. The "ttrow" and "ttcol" variables are set to a crazy value to - * ensure that the next call to "ttmove" does not turn into a no-op (the - * window adjustment moves the cursor). - */ -void -ttwindow(int top, int bot) -{ - if (change_scroll_region && (tttop != top || ttbot != bot)) { - putpad(tgoto(change_scroll_region, bot, top), nrow - ttrow); - ttrow = HUGE; /* Unknown. */ - ttcol = HUGE; - tttop = top; /* Remember region. */ - ttbot = bot; - } -} - -/* - * Switch to full screen scroll. This is used by "spawn.c" just before it - * suspends the editor and by "display.c" when it is getting ready to - * exit. This function does a full screen scroll by telling the terminal - * to set a scrolling region that is lines or nrow rows high, whichever is - * larger. This behavior seems to work right on systems where you can set - * your terminal size. - */ -void -ttnowindow(void) -{ - if (change_scroll_region) { - putpad(tgoto(change_scroll_region, - (nrow > lines ? nrow : lines) - 1, 0), nrow - ttrow); - ttrow = HUGE; /* Unknown. */ - ttcol = HUGE; - tttop = HUGE; /* No scroll region. */ - ttbot = HUGE; - } -} - -/* - * Set the current writing color to the specified color. Watch for color - * changes that are not going to do anything (the color is already right) - * and don't send anything to the display. The rainbow version does this - * in putline.s on a line by line basis, so don't bother sending out the - * color shift. - */ -void -ttcolor(int color) -{ - if (color != tthue) { - if (color == CTEXT) - /* normal video */ - putpad(exit_standout_mode, 1); - else if (color == CMODE) - /* reverse video */ - putpad(enter_standout_mode, 1); - /* save the color */ - tthue = color; - } -} - -/* - * This routine is called by the "refresh the screen" command to try - * to resize the display. Look in "window.c" to see how - * the caller deals with a change. - * - * We use `newrow' and `newcol' so vtresize() know the difference between the - * new and old settings. - */ -void -ttresize(void) -{ - int newrow = 0, newcol = 0; - -#ifdef TIOCGWINSZ - struct winsize winsize; - - if (ioctl(0, TIOCGWINSZ, &winsize) == 0) { - newrow = winsize.ws_row; - newcol = winsize.ws_col; - } -#endif - if ((newrow <= 0 || newcol <= 0) && - ((newrow = lines) <= 0 || (newcol = columns) <= 0)) { - newrow = 24; - newcol = 80; - } - if (vtresize(1, newrow, newcol) != TRUE) - panic("vtresize failed"); -} - -/* - * fake char output for charcost() - */ -/* ARGSUSED */ -static int -fakec(int c) -{ - cci++; - return (0); -} - -/* calculate the cost of doing string s */ -static int -charcost(char *s) -{ - cci = 0; - - tputs(s, nrow, fakec); - return (cci); -} diff --git a/mg/ttydef.h b/mg/ttydef.h deleted file mode 100644 index b32b1c0..0000000 --- a/mg/ttydef.h +++ /dev/null @@ -1,25 +0,0 @@ -/* $OpenBSD: ttydef.h,v 1.10 2005/11/20 03:53:45 deraadt Exp $ */ - -/* This file is in the public domain. */ - -#ifndef TTYDEF_H -#define TTYDEF_H - -/* - * Terminfo terminal file, nothing special, just make it big - * enough for windowing systems. - */ - -#define STANDOUT_GLITCH /* possible standout glitch */ -#define TERMCAP /* for possible use in ttyio.c */ - -#ifdef undef -#define MOVE_STANDOUT /* don't move in standout mode */ -#endif /* undef */ - -#define putpad(str, num) tputs(str, num, ttputc) - -#define KFIRST K00 -#define KLAST K00 - -#endif /* TTYDEF_H */ diff --git a/mg/ttyio.c b/mg/ttyio.c deleted file mode 100644 index 228a370..0000000 --- a/mg/ttyio.c +++ /dev/null @@ -1,225 +0,0 @@ -/* $OpenBSD: ttyio.c,v 1.32 2008/02/05 12:53:38 reyk Exp $ */ - -/* This file is in the public domain. */ - -/* - * POSIX terminal I/O. - * - * The functions in this file negotiate with the operating system for - * keyboard characters, and write characters to the display in a barely - * buffered fashion. - */ -#include "def.h" - -#include -#include -#include -#include -#include -#include - -#define NOBUF 512 /* Output buffer size. */ - -#ifndef TCSASOFT -#define TCSASOFT 0 -#endif - -int ttstarted; -char obuf[NOBUF]; /* Output buffer. */ -size_t nobuf; /* Buffer count. */ -struct termios oldtty; /* POSIX tty settings. */ -struct termios newtty; -int nrow; /* Terminal size, rows. */ -int ncol; /* Terminal size, columns. */ - -/* - * This function gets called once, to set up the terminal. - * On systems w/o TCSASOFT we turn off off flow control, - * which isn't really the right thing to do. - */ -void -ttopen(void) -{ - if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO)) - panic("standard input and output must be a terminal"); - - if (ttraw() == FALSE) - panic("aborting due to terminal initialize failure"); -} - -/* - * This function sets the terminal to RAW mode, as defined for the current - * shell. This is called both by ttopen() above and by spawncli() to - * get the current terminal settings and then change them to what - * mg expects. Thus, tty changes done while spawncli() is in effect - * will be reflected in mg. - */ -int -ttraw(void) -{ - if (tcgetattr(0, &oldtty) < 0) { - ewprintf("ttopen can't get terminal attributes"); - return (FALSE); - } - (void)memcpy(&newtty, &oldtty, sizeof(newtty)); - /* Set terminal to 'raw' mode and ignore a 'break' */ - newtty.c_cc[VMIN] = 1; - newtty.c_cc[VTIME] = 0; - newtty.c_iflag |= IGNBRK; - newtty.c_iflag &= ~(BRKINT | PARMRK | INLCR | IGNCR | ICRNL | IXON); - newtty.c_oflag &= ~OPOST; - newtty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - -#if !TCSASOFT - /* - * If we don't have TCSASOFT, force terminal to - * 8 bits, no parity. - */ - newtty.c_iflag &= ~ISTRIP; - newtty.c_cflag &= ~(CSIZE | PARENB); - newtty.c_cflag |= CS8; -#endif - if (tcsetattr(0, TCSASOFT | TCSADRAIN, &newtty) < 0) { - ewprintf("ttopen can't tcsetattr"); - return (FALSE); - } - ttstarted = 1; - - return (TRUE); -} - -/* - * This function gets called just before we go back home to the shell. - * Put all of the terminal parameters back. - * Under UN*X this just calls ttcooked(), but the ttclose() hook is in - * because vttidy() in display.c expects it for portability reasons. - */ -void -ttclose(void) -{ - if (ttstarted) { - if (ttcooked() == FALSE) - panic(""); /* ttcooked() already printf'd */ - ttstarted = 0; - } -} - -/* - * This function restores all terminal settings to their default values, - * in anticipation of exiting or suspending the editor. - */ -int -ttcooked(void) -{ - ttflush(); - if (tcsetattr(0, TCSASOFT | TCSADRAIN, &oldtty) < 0) { - ewprintf("ttclose can't tcsetattr"); - return (FALSE); - } - return (TRUE); -} - -/* - * Write character to the display. Characters are buffered up, - * to make things a little bit more efficient. - */ -int -ttputc(int c) -{ - if (nobuf >= NOBUF) - ttflush(); - obuf[nobuf++] = c; - return (c); -} - -/* - * Flush output. - */ -void -ttflush(void) -{ - ssize_t written; - char *buf = obuf; - - if (nobuf == 0) - return; - - while ((written = write(fileno(stdout), buf, nobuf)) != nobuf) { - if (written == -1) { - if (errno == EINTR) - continue; - panic("ttflush write failed"); - } - buf += written; - nobuf -= written; - } - nobuf = 0; -} - -/* - * Read character from terminal. All 8 bits are returned, so that you - * can use a multi-national terminal. - */ -int -ttgetc(void) -{ - char c; - ssize_t ret; - - do { - ret = read(STDIN_FILENO, &c, 1); - if (ret == -1 && errno == EINTR) { - if (winch_flag) { - redraw(0, 0); - winch_flag = 0; - } - } else if (ret == 1) - break; - } while (1); - return ((int) c) & 0xFF; -} - -/* - * Returns TRUE if there are characters waiting to be read. - */ -int -charswaiting(void) -{ - int x; - - return ((ioctl(0, FIONREAD, &x) < 0) ? 0 : x); -} - -/* - * panic - just exit, as quickly as we can. - */ -void -panic(char *s) -{ - ttclose(); - (void) fputs("panic: ", stderr); - (void) fputs(s, stderr); - (void) fputc('\n', stderr); - exit(1); -} - -/* - * This function returns FALSE if any characters have showed up on the - * tty before 'msec' milliseconds. - */ -int -ttwait(int msec) -{ - fd_set readfds; - struct timeval tmout; - - FD_ZERO(&readfds); - FD_SET(0, &readfds); - - tmout.tv_sec = msec/1000; - tmout.tv_usec = msec - tmout.tv_sec * 1000; - - if ((select(1, &readfds, NULL, NULL, &tmout)) == 0) - return (TRUE); - return (FALSE); -} diff --git a/mg/ttykbd.c b/mg/ttykbd.c deleted file mode 100644 index a160a3e..0000000 --- a/mg/ttykbd.c +++ /dev/null @@ -1,89 +0,0 @@ -/* $OpenBSD: ttykbd.c,v 1.16 2012/04/12 04:47:59 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Name: MG 2a - * Terminfo keyboard driver using key files - * Created: 22-Nov-1987 Mic Kaczmarczik (mic@emx.cc.utexas.edu) - */ - -#include "def.h" -#include "kbd.h" - -#ifdef XKEYS -#include - -#ifdef FKEYS -/* - * Get keyboard character. Very simple if you use keymaps and keys files. - * Bob was right -- the old XKEYS code is not the right solution. - * FKEYS code is not useful other than to help debug FKEYS code in - * extend.c. - */ - -char *keystrings[] = {NULL}; -#endif /* FKEYS */ - -/* - * Turn on function keys using keypad_xmit, then load a keys file, if - * available. The keys file is located in the same manner as the startup - * file is, depending on what startupfile() does on your system. - */ -void -ttykeymapinit(void) -{ - char *cp; - -#ifdef FKEYS - /* Bind keypad function keys. */ - if (key_left) - dobindkey(fundamental_map, "backward-char", key_left); - if (key_right) - dobindkey(fundamental_map, "forward-char", key_right); - if (key_up) - dobindkey(fundamental_map, "previous-line", key_up); - if (key_down) - dobindkey(fundamental_map, "next-line", key_down); - if (key_beg) - dobindkey(fundamental_map, "beginning-of-line", key_beg); - else if (key_home) - dobindkey(fundamental_map, "beginning-of-line", key_home); - if (key_end) - dobindkey(fundamental_map, "end-of-line", key_end); - if (key_npage) - dobindkey(fundamental_map, "scroll-up", key_npage); - if (key_ppage) - dobindkey(fundamental_map, "scroll-down", key_ppage); - if (key_dc) - dobindkey(fundamental_map, "delete-char", key_dc); -#endif /* FKEYS */ - - if ((cp = getenv("TERM"))) { - if (((cp = startupfile(cp)) != NULL) && (load(cp) != TRUE)) - ewprintf("Error reading key initialization file"); - } - if (keypad_xmit) - /* turn on keypad */ - putpad(keypad_xmit, 1); -} - -/* - * Clean up the keyboard -- called by tttidy() - */ -void -ttykeymaptidy(void) -{ - if (keypad_local) - /* turn off keypad */ - putpad(keypad_local, 1); -} - -#else - -void -ttykeymapinit(void) -{ -} - -#endif /* XKEYS */ diff --git a/mg/tutorial b/mg/tutorial deleted file mode 100644 index f025f67..0000000 --- a/mg/tutorial +++ /dev/null @@ -1,349 +0,0 @@ -The mg Tutorial ---------------- - -The mg editor is a public domain editor intended to loosely resemble GNU Emacs, -while still retaining fast speed and a small memory footprint. - -Most mg commands involve using the Control (sometimes labelled "Ctrl") or the -Meta (sometimes labelled "Alt") key. We will use the following conventions in -this tutorial: - - C- means hold down the Control key while typing the character . - M- means hold down the Meta key while typing the character . - -If you don't have a Meta key, you can use Esc instead. Press and release the -Esc key and type . This is equivalent to M-. - -The first thing to learn is how to move up and down a document. To move your -cursor down, use the down-arrow cursor key or C-n (Control and n). - ->> Now type C-n multiple times and move your cursor past this line. - -Congratulations. You have now learned how to move your cursor down. Note how -mg has redrawn your screen so that the cursor is now in the middle of the -screen. This is a feature of mg, which allows you to see the lines before and -after the current cursor position. - -To move your cursor up, you can use the up-arrow cursor key or C-p (Control and -p). - ->> Try using C-p and C-n to move up and down and then move past this line. - -The next commands to learn are how to move your cursor left and right. To do -this, you can use the left-arrow and right-arrow cursor keys. Alternatively, -you can use C-b and C-f to do this. - ->> Practise using the arrow keys or C-b and C-f on this line. - -To make it easy to remember these commands, it helps to remember by letter: -P - Previous line, N - Next line, B - Backwards and F - Forward. - -Now that you've learned how to move single characters at a time, next we learn -how to move one word at a time. To do this, you can use M-f (Meta and f) or -M-b (Meta and b) to move forwards and backwards, one word at a time. - ->> Try moving one word at a time by using M-f and M-b on this line. - -Notice how the Ctrl and Meta key combinations perform related functions. C-f -moves one letter forward, whereas M-f moves one word forward. There are many -key combinations in mg, where C- will perform one function and M- -will perform a similar related function. - -Next, we will learn how to refresh and redraw the screen. - ->> Now move the cursor down to this line and then type C-l (that's Control and - lowercase L) to refresh the screen. - -Note that C-l refreshes the screen and centers it on the line you typed it on. - -To move to the beginning or end of a line, you can use the Home and End keys, -or you can use C-a and C-e to move to the beginning and end. - ->> Use C-a and C-e to move to the beginning and end of this line. - -The next commands we will learn is how to move up and down, one page at a time. -To do this, you can use the Page Up (sometimes labelled PgUp) and Page Down -(sometimes labelled PgDn) keys. You can also use C-v and M-v to do this. C-v -moves the cursor down one page and M-v moves it up one page. - ->> Try using M-v and C-v to move up and down, one page at a time. - -The final two motion commands we will learn are M-< (Meta-Less than) and -M-> (Meta-Greater than) which move you to the beginning and end of a file, -respectively. You may not want to try that now as you will probably lose your -place in this tutorial. Note that on most terminals, < is above the , key, so -you'll need to press the Shift key to type <. - -Movement Summary ------------------ - -The following is a summary of the movement commands we've learned so far: - - C-f Move forward one character (can also use right arrow key). - C-b Move backward one character (can also use left arrow key). - C-p Move up one line (can also use up arrow key). - C-n Move down one line (can also use down arrow key). - M-f Move forward one word. - M-b Move backward one word. - C-a Move to beginning of line (can also use Home key). - C-e Move to end of line (can also use End key). - C-v Move forward one page (can also use PgDn/Page Down key). - M-v Move backward one page (can also use PgUp/Page Up key). - M-< Move to beginning of file. - M-> Move to end of file. - -Now that you've mastered the basics of moving around in mg, you can cause mg -to execute these commands multiple times. The way to do this is to type C-u -followed by some digits followed by a movement command. - ->> Type C-u 5 C-f to move forward 5 characters. - -In general, C-u allows you to execute any command multiple times, not just -cursor motion commands. The only exception to this rule are C-v and M-v. -When using these two commands with an argument, they move the cursor by that -many lines instead of pages. - -Cancelling mg Commands ----------------------- - -If you have started typing out a command that you didn't mean to finish, you -can use the C-g command to cancel the command immediately. - ->> For example, type C-u 50 and then type C-g to cancel the C-u command. ->> Type Esc and then C-g to cancel the Esc key. - -In general, you can use C-g to stop any mg commands. You may type it multiple -times if you wish. You should see the word "Quit" appear in the bottom of the -screen when you type C-g indicating that a command was cancelled. - -In general, when in doubt, use C-g to get out of trouble. - - -Inserting/Deleting Text ------------------------ - -To insert text anywhere, simply move your cursor to the appropriate position -and begin typing. To delete characters, use the backspace key. If you use -M- (Meta and backspace key), you will delete one word instead -of one character at a time. - -To delete characters to the right of the cursor, you can use C-d to delete -characters to the right of the current position. If you use M-d instead of -C-d, you can delete one word at a time instead of one character at a time. - ->> Try inserting and deleting characters and words on this line. - -Note that if you type too many characters on a single line, the line will -scroll off the screen and you will see a $ on the line to indicate that the -line is too long to fit on the screen at one time. - -To delete a line at a time, you can use C-k to kill the line from the current -cursor position to the end of the line. You can type C-k multiple times to -kill many lines. - -You can issue insert or delete commands multiple times using C-u. For example, -C-u 10 e will type out eeeeeeeeee, C-u 4 M-d will delete four words to the -right of the cursor and so on. - -To undo any operation, you can use C-_ (That's control-underscore). - -Now if you kill something that you didn't mean to, you can yank it back from -the dead by using C-y. In general, when you kill something bigger than a single -character, mg saves it in a buffer somewhere and you can restore it by using -C-y. This is useful for moving text around. You can kill text in one place, -move your cursor to the new location and then use C-y to paste it there. - -Search for Text ---------------- - -To search for text, type C-s followed by the text you wish to search for. Note -that as you start typing the characters, mg automatically searches as you type -the characters. - -To continue searching the text you're looking for, type C-s to find the next -instance. To search in reverse, type C-r instead of C-s. If you type C-s or -C-r twice, it will simply search for the last text that you searched for. - -To stop searching for text, simply use the cursor keys (or C-f, C-b etc.) or -C-g to stop the search operation. - ->> Use C-s foo to search for "foo" in the text. You can use C-s again to - find other instances of foo in the file. - -Note that if a word cannot be found, it will say Failing I-search: at the -bottom of the screen. Typing C-s again will wrap the search around from the -top of the file and begin searching from there. - -Replace Text ------------- - -To replace text, use M-%. You will be prompted for the text to search for and -the text to replace it with. You will then be taken to the first instance of -text from the current position. At this point you can do one of the following: - - y - Replace the text at this instance and search for more items. - n - Skip this instance and search for more items. - . or Enter - Stop replacing text (You can also use C-g). - ! - Replace all the instances without prompting at each one. - ->> Try replacing "frobnitz" with "zutwalt" on this line. - -Cut/Copy/Paste Text -------------------- - -As explained above, you can cut regions using C-k to kill multiple lines. To -paste the text that you just cut, simply move your cursor to the point and -then type C-y to restore the text. You may type C-y multiple times to restore -the text. Hence, to copy text, you can use C-k to kill all the lines, use C-y -to restore it immediately, then move to the region you want to copy it to and -then type C-y again to restore the last cut text block again. - -Another way to cut or copy chunks of text is to first position your cursor at -the starting point of the chunk of text. Then type C- to mark this as -the starting point to cut or copy. Then move the cursor to the end point of the -text chunk that you wish to manipulate. Then type C-w to cut the region, or -M-w to copy the region. If you wish to cancel marking a block of text, simply -type C-g to cancel the operation. - -To paste the region that you've cut or copied above, simply move your cursor -to the desired location and then type C-y to paste it. - -Status Line ------------ - -At the bottom of your screen is a reverse highlighted line. This is the status -line and lets you know some useful information about the file you're editing. - -On the status line, you should see "Mg: tutorial". This lets you know that -you're editing a file named "tutorial". If you've edited this file and not -saved it, it should have a "**" to the left of those words. If this file is -read-only, you should see a "%%" to the left of those words. - -To the right of the status line, you should see L followed by digits and C -followed by some more digits. These indicate the line number and column number -of the file that your cursor is currently on. If you move the cursor around, -you should see the line and column number change. - -In the middle of the screen, you should see the word "(fundamental)" which -indicates that the current editing mode is "fundamental-mode". The mg editor -also supports a c-mode that is more suited to editing C code. There are also -some other useful editing modes for different situations. See the man page -for mg(1) to learn about the various editing modes. - -Opening and Saving Files ------------------------- - -To open a file, you can use C-x C-f. You will then be prompted for a file name. -If you type a file name that doesn't already exist, a new file will be opened -for you. If the file name already exists, then it will be opened for you and -you can begin editing it. Note that you do not need to type the whole file -name for an existing file. You can type part of the file name and then press -the TAB key. If there is only file name that matches, mg will fill in the rest -of the file name for you. If there are multiple files, mg will display that -the choice is ambiguous. If you type the TAB key again, mg will show you all -the available choices for file names. - -NOTE: If you type C-x f instead of C-x C-f, you can use C-g to cancel the -Set-Fill-Column command. You can also use C-g to cancel the C-x C-f command -if you don't wish to open a new file. - -To save the file once you've edited it, use C-x C-s to save the file. When -mg is done saving the file, you should see the words "Wrote /path/to/file" -in the bottom of your screen. In general, it is a good idea to save quite -often. When you save a file, mg saves a backup of the file with a tilde (~) -character at the end. - -Windows -------- - -The mg editor can support several windows at the same time, each one displaying -different text. To split a screen into two horizontal windows use C-x 2 to do -this. To return to one window, use C-x 1 to close the other windows and only -keep the current window. - ->> Use C-x 2 to split the screen into two windows. - ->> Use C-x o to move from one window to the other. You can scroll up and down - in each window using the cursor keys or C-n and C-p keys. - ->> Use C-x 1 to restore back to one window. - -Buffers -------- - -The mg editor is capable of editing multiple files at the same time. When you -open a second file with C-x C-f, the first file is still being edited by mg. -You can list all the buffers that are opened by mg by typing C-x C-b. The -screen should divide into two and the top window will list the buffers that -are currently open. Use C-x o to switch to the top window (we already learned -this key combination above in the Windows section) and then use the arrow keys -to move to the buffer you wish to switch to and then type the Enter key to -select that buffer. Then use C-x 1 to switch back to only one window. - -You may also move back to the last opened buffer by using C-x b to toggle back -and forth between two buffers. Note the difference between C-x b and C-x C-b. - ->> Use C-x C-f to open a new file ->> Use C-x b to switch back and forth between that buffer and this one. - -To edit files in multiple windows, use C-x 2 to split the screen into two -windows. Then use C-x C-f to open a new file in one of the two windows. You -can then switch between the two windows using C-x o. You can switch between -buffers in any window using C-x b. To go back to one window, use C-x 1. - -To kill any buffer, use C-x k. You will be prompted for the buffer to kill. -By default, the current buffer is selected as the one to kill. You may also -type another buffer name or use C-g to cancel the operation. - -Extended Commands ------------------ - -The mg editor has several extended commands, more than what can be covered -by the Control and Meta keys. The mg editor gets around this by using what is -called the X (eXtend) command. There are two forms of this: - - C-x Character eXtension. Followed by one character. - M-x Named character eXtension. Followed by a long command. - -You've already seen C-x C-f and C-x C-s to open and save a file. There are -other longer commands. For instance, you can also open a file by typing -M-x open-file Enter. When you type a command using M-x, mg prompts you for -the command at the bottom of the screen. You can type out the whole command -if you wish, or you can type out part of the command and then use the TAB key -for autocompleting the command. - -For instance, to replace text, you can type M-x repl TAB enter to execute -the replace-text command. To cancel this command, type C-g. - -To see a list of all available mg(1) commands, consult the man page. - -Exiting mg ----------- - -To exit mg temporarily and return to the shell, use C-z. This will take you -back to the command shell. To return back to mg, type fg in the shell and you -will be returned to your mg session. - -To exit mg permanently, type C-x C-c. If you have any unsaved buffers, you -will be asked if you wish to save them or not. - -Conclusion ----------- - -This tutorial is meant to get new users up and running with mg. There is more -information available via the mg(1) man page. If you have any suggestions for -improvement, please don't hesitate to drop a message or (better still) submit -a diff to tech@openbsd.org. - -Author Info ------------ - -Original Author of this document: Mayukh Bose, -Date last updated: 2012-05-25 - -Copyright ---------- - -None. This document is in the public domain. - - diff --git a/mg/undo.c b/mg/undo.c deleted file mode 100644 index 1efd2a1..0000000 --- a/mg/undo.c +++ /dev/null @@ -1,585 +0,0 @@ -/* $OpenBSD: undo.c,v 1.50 2010/06/30 19:12:54 oga Exp $ */ -/* - * This file is in the public domain - */ - -#include "def.h" -#include "kbd.h" - -#define MAX_FREE_RECORDS 32 - -/* - * Local variables - */ -static struct undoq undo_free; -static int undo_free_num; -static int boundary_flag = TRUE; -static int undo_enable_flag = TRUE; - -/* - * Local functions - */ -static int find_dot(struct line *, int); -static int find_lo(int, struct line **, int *, int *); -static struct undo_rec *new_undo_record(void); -static int drop_oldest_undo_record(void); - -/* - * find_dot, find_lo() - * - * Find an absolute dot in the buffer from a line/offset pair, and vice-versa. - * - * Since lines can be deleted while they are referenced by undo record, we - * need to have an absolute dot to have something reliable. - */ -static int -find_dot(struct line *lp, int off) -{ - int count = 0; - struct line *p; - - for (p = curbp->b_headp; p != lp; p = lforw(p)) { - if (count != 0) { - if (p == curbp->b_headp) { - ewprintf("Error: Undo stuff called with a" - "nonexistent line"); - return (FALSE); - } - } - count += llength(p) + 1; - } - count += off; - - return (count); -} - -static int -find_lo(int pos, struct line **olp, int *offset, int *lnum) -{ - struct line *p; - int lineno; - - p = curbp->b_headp; - lineno = 0; - while (pos > llength(p)) { - pos -= llength(p) + 1; - if ((p = lforw(p)) == curbp->b_headp) { - *olp = NULL; - *offset = 0; - return (FALSE); - } - lineno++; - } - *olp = p; - *offset = pos; - *lnum = lineno; - - return (TRUE); -} - -static struct undo_rec * -new_undo_record(void) -{ - struct undo_rec *rec; - - rec = TAILQ_FIRST(&undo_free); - if (rec != NULL) { - /* Remove it from the free-list */ - TAILQ_REMOVE(&undo_free, rec, next); - undo_free_num--; - } else { - if ((rec = malloc(sizeof(*rec))) == NULL) - panic("Out of memory in undo code (record)"); - } - memset(rec, 0, sizeof(struct undo_rec)); - - return (rec); -} - -void -free_undo_record(struct undo_rec *rec) -{ - static int initialised = 0; - - /* - * On the first run, do initialisation of the free list. - */ - if (initialised == 0) { - TAILQ_INIT(&undo_free); - initialised = 1; - } - if (rec->content != NULL) { - free(rec->content); - rec->content = NULL; - } - if (undo_free_num >= MAX_FREE_RECORDS) { - free(rec); - return; - } - undo_free_num++; - - TAILQ_INSERT_HEAD(&undo_free, rec, next); -} - -/* - * Drop the oldest undo record in our list. Return 1 if we could remove it, - * 0 if the undo list was empty. - */ -static int -drop_oldest_undo_record(void) -{ - struct undo_rec *rec; - - rec = TAILQ_LAST(&curbp->b_undo, undoq); - if (rec != NULL) { - undo_free_num--; - TAILQ_REMOVE(&curbp->b_undo, rec, next); - free_undo_record(rec); - return (1); - } - return (0); -} - -static int -lastrectype(void) -{ - struct undo_rec *rec; - - if ((rec = TAILQ_FIRST(&curbp->b_undo)) != NULL) - return (rec->type); - return (0); -} - -/* - * Returns TRUE if undo is enabled, FALSE otherwise. - */ -int -undo_enabled(void) -{ - return (undo_enable_flag); -} - -/* - * undo_enable: toggle undo_enable. - * Returns the previous value of the flag. - */ -int -undo_enable(int f, int n) -{ - int pon = undo_enable_flag; - - if (f & (FFARG | FFRAND)) - undo_enable_flag = n > 0; - else - undo_enable_flag = !undo_enable_flag; - - if (!(f & FFRAND)) - ewprintf("Undo %sabled", undo_enable_flag ? "en" : "dis"); - - return (pon); -} - -/* - * If undo is enabled, then: - * Toggle undo boundary recording. - * If called with an argument, (n > 0) => enable. Otherwise disable. - * In either case, add an undo boundary - * If undo is disabled, this function has no effect. - */ -int -undo_boundary_enable(int f, int n) -{ - int bon = boundary_flag; - - if (!undo_enable_flag) - return (FALSE); - - undo_add_boundary(FFRAND, 1); - - if (f & (FFARG | FFRAND)) - boundary_flag = n > 0; - else - boundary_flag = !boundary_flag; - - if (!(f & FFRAND)) - ewprintf("Undo boundaries %sabled", - boundary_flag ? "en" : "dis"); - - return (bon); -} - -/* - * Record an undo boundary, unless boundary_flag == FALSE. - * Does nothing if previous undo entry is already a boundary or 'modified' flag. - */ -int -undo_add_boundary(int f, int n) -{ - struct undo_rec *rec; - int last; - - if (boundary_flag == FALSE) - return (FALSE); - - last = lastrectype(); - if (last == BOUNDARY || last == MODIFIED) - return (TRUE); - - rec = new_undo_record(); - rec->type = BOUNDARY; - - TAILQ_INSERT_HEAD(&curbp->b_undo, rec, next); - - return (TRUE); -} - -/* - * Record an undo "modified" boundary - */ -void -undo_add_modified(void) -{ - struct undo_rec *rec; - - rec = new_undo_record(); - rec->type = MODIFIED; - - TAILQ_INSERT_HEAD(&curbp->b_undo, rec, next); - - return; -} - -int -undo_add_insert(struct line *lp, int offset, int size) -{ - struct region reg; - struct undo_rec *rec; - int pos; - - if (!undo_enable_flag) - return (TRUE); - reg.r_linep = lp; - reg.r_offset = offset; - reg.r_size = size; - - pos = find_dot(lp, offset); - - /* - * We try to reuse the last undo record to `compress' things. - */ - rec = TAILQ_FIRST(&curbp->b_undo); - if (rec != NULL && rec->type == INSERT) { - if (rec->pos + rec->region.r_size == pos) { - rec->region.r_size += reg.r_size; - return (TRUE); - } - } - - /* - * We couldn't reuse the last undo record, so prepare a new one. - */ - rec = new_undo_record(); - rec->pos = pos; - rec->type = INSERT; - memmove(&rec->region, ®, sizeof(struct region)); - rec->content = NULL; - - undo_add_boundary(FFRAND, 1); - - TAILQ_INSERT_HEAD(&curbp->b_undo, rec, next); - - return (TRUE); -} - -/* - * This of course must be done _before_ the actual deletion is done. - */ -int -undo_add_delete(struct line *lp, int offset, int size, int isreg) -{ - struct region reg; - struct undo_rec *rec; - int pos; - - if (!undo_enable_flag) - return (TRUE); - - reg.r_linep = lp; - reg.r_offset = offset; - reg.r_size = size; - - pos = find_dot(lp, offset); - - if (offset == llength(lp)) /* if it's a newline... */ - undo_add_boundary(FFRAND, 1); - else if ((rec = TAILQ_FIRST(&curbp->b_undo)) != NULL) { - /* - * Separate this command from the previous one if we're not - * just before the previous record... - */ - if (!isreg && rec->type == DELETE) { - if (rec->pos - rec->region.r_size != pos) - undo_add_boundary(FFRAND, 1); - } - } - rec = new_undo_record(); - rec->pos = pos; - if (isreg) - rec->type = DELREG; - else - rec->type = DELETE; - memmove(&rec->region, ®, sizeof(struct region)); - do { - rec->content = malloc(reg.r_size + 1); - } while ((rec->content == NULL) && drop_oldest_undo_record()); - - if (rec->content == NULL) - panic("Out of memory"); - - region_get_data(®, rec->content, reg.r_size); - - if (isreg || lastrectype() != DELETE) - undo_add_boundary(FFRAND, 1); - - TAILQ_INSERT_HEAD(&curbp->b_undo, rec, next); - - return (TRUE); -} - -/* - * This of course must be called before the change takes place. - */ -int -undo_add_change(struct line *lp, int offset, int size) -{ - if (!undo_enable_flag) - return (TRUE); - undo_add_boundary(FFRAND, 1); - boundary_flag = FALSE; - undo_add_delete(lp, offset, size, 0); - undo_add_insert(lp, offset, size); - boundary_flag = TRUE; - undo_add_boundary(FFRAND, 1); - - return (TRUE); -} - -/* - * Show the undo records for the current buffer in a new buffer. - */ -/* ARGSUSED */ -int -undo_dump(int f, int n) -{ - struct undo_rec *rec; - struct buffer *bp; - struct mgwin *wp; - char buf[4096], tmp[1024]; - int num; - - /* - * Prepare the buffer for insertion. - */ - if ((bp = bfind("*undo*", TRUE)) == NULL) - return (FALSE); - bp->b_flag |= BFREADONLY; - bclear(bp); - popbuf(bp, WNONE); - - for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { - if (wp->w_bufp == bp) { - wp->w_dotp = bp->b_headp; - wp->w_doto = 0; - } - } - - num = 0; - TAILQ_FOREACH(rec, &curbp->b_undo, next) { - num++; - snprintf(buf, sizeof(buf), - "%d:\t %s at %d ", num, - (rec->type == DELETE) ? "DELETE": - (rec->type == DELREG) ? "DELREGION": - (rec->type == INSERT) ? "INSERT": - (rec->type == BOUNDARY) ? "----" : - (rec->type == MODIFIED) ? "MODIFIED": "UNKNOWN", - rec->pos); - - if (rec->content) { - (void)strlcat(buf, "\"", sizeof(buf)); - snprintf(tmp, sizeof(tmp), "%.*s", rec->region.r_size, - rec->content); - (void)strlcat(buf, tmp, sizeof(buf)); - (void)strlcat(buf, "\"", sizeof(buf)); - } - snprintf(tmp, sizeof(tmp), " [%d]", rec->region.r_size); - if (strlcat(buf, tmp, sizeof(buf)) >= sizeof(buf)) { - ewprintf("Undo record too large. Aborted."); - return (FALSE); - } - addlinef(bp, "%s", buf); - } - return (TRUE); -} - -/* - * After the user did action1, then action2, then action3: - * - * [action3] <--- Undoptr - * [action2] - * [action1] - * ------ - * [undo] - * - * After undo: - * - * [undo of action3] - * [action2] <--- Undoptr - * [action1] - * ------ - * [undo] - * - * After another undo: - * - * - * [undo of action2] - * [undo of action3] - * [action1] <--- Undoptr - * ------ - * [undo] - * - * Note that the "undo of actionX" have no special meaning. Only when - * we undo a deletion, the insertion will be recorded just as if it - * was typed on the keyboard. Resulting in the inverse operation being - * saved in the list. - * - * If undoptr reaches the bottom of the list, or if we moved between - * two undo actions, we make it point back at the topmost record. This is - * how we handle redoing. - */ -/* ARGSUSED */ -int -undo(int f, int n) -{ - struct undo_rec *ptr, *nptr; - int done, rval; - struct line *lp; - int offset, save, dot; - static int nulled = FALSE; - int lineno; - - if (n < 0) - return (FALSE); - - dot = find_dot(curwp->w_dotp, curwp->w_doto); - - ptr = curbp->b_undoptr; - - /* first invocation, make ptr point back to the top of the list */ - if ((ptr == NULL && nulled == TRUE) || rptcount == 0) { - ptr = TAILQ_FIRST(&curbp->b_undo); - nulled = TRUE; - } - - rval = TRUE; - while (n--) { - /* if we have a spurious boundary, free it and move on.... */ - while (ptr && ptr->type == BOUNDARY) { - nptr = TAILQ_NEXT(ptr, next); - TAILQ_REMOVE(&curbp->b_undo, ptr, next); - free_undo_record(ptr); - ptr = nptr; - } - /* - * Ptr is NULL, but on the next run, it will point to the - * top again, redoing all stuff done in the buffer since - * its creation. - */ - if (ptr == NULL) { - ewprintf("No further undo information"); - rval = FALSE; - nulled = TRUE; - break; - } - nulled = FALSE; - - /* - * Loop while we don't get a boundary specifying we've - * finished the current action... - */ - - undo_add_boundary(FFRAND, 1); - - save = boundary_flag; - boundary_flag = FALSE; - - done = 0; - do { - /* - * Move to where this has to apply - * - * Boundaries (and the modified flag) are put as - * position 0 (to save lookup time in find_dot) - * so we must not move there... - */ - if (ptr->type != BOUNDARY && ptr->type != MODIFIED) { - if (find_lo(ptr->pos, &lp, - &offset, &lineno) == FALSE) { - ewprintf("Internal error in Undo!"); - rval = FALSE; - break; - } - curwp->w_dotp = lp; - curwp->w_doto = offset; - curwp->w_markline = curwp->w_dotline; - curwp->w_dotline = lineno; - } - - /* - * Do operation^-1 - */ - switch (ptr->type) { - case INSERT: - ldelete(ptr->region.r_size, KNONE); - break; - case DELETE: - lp = curwp->w_dotp; - offset = curwp->w_doto; - region_put_data(ptr->content, - ptr->region.r_size); - curwp->w_dotp = lp; - curwp->w_doto = offset; - break; - case DELREG: - region_put_data(ptr->content, - ptr->region.r_size); - break; - case BOUNDARY: - done = 1; - break; - case MODIFIED: - curbp->b_flag &= ~BFCHG; - break; - default: - break; - } - - /* And move to next record */ - ptr = TAILQ_NEXT(ptr, next); - } while (ptr != NULL && !done); - - boundary_flag = save; - undo_add_boundary(FFRAND, 1); - - ewprintf("Undo!"); - } - /* - * Record where we are. (we have to save our new position at the end - * since we change the dot when undoing....) - */ - curbp->b_undoptr = ptr; - - curbp->b_undopos = find_dot(curwp->w_dotp, curwp->w_doto); - - return (rval); -} diff --git a/mg/version.c b/mg/version.c deleted file mode 100644 index 2dc08cd..0000000 --- a/mg/version.c +++ /dev/null @@ -1,24 +0,0 @@ -/* $OpenBSD: version.c,v 1.9 2005/06/14 18:14:40 kjell Exp $ */ - -/* This file is in the public domain. */ - -/* - * This file contains the string that gets written - * out by the emacs-version command. - */ - -#include "def.h" - -const char version[] = "Mg 2a"; - -/* - * Display the version. All this does - * is copy the version string onto the echo line. - */ -/* ARGSUSED */ -int -showversion(int f, int n) -{ - ewprintf("%s", version); - return (TRUE); -} diff --git a/mg/window.c b/mg/window.c deleted file mode 100644 index db913c9..0000000 --- a/mg/window.c +++ /dev/null @@ -1,428 +0,0 @@ -/* $OpenBSD: window.c,v 1.28 2011/08/01 12:15:23 lum Exp $ */ - -/* This file is in the public domain. */ - -/* - * Window handling. - */ - -#include "def.h" - -struct mgwin * -new_window(struct buffer *bp) -{ - struct mgwin *wp; - - wp = calloc(1, sizeof(struct mgwin)); - if (wp == NULL) - return (NULL); - - wp->w_bufp = bp; - wp->w_dotp = NULL; - wp->w_doto = 0; - wp->w_markp = NULL; - wp->w_marko = 0; - wp->w_rflag = 0; - wp->w_frame = 0; - wp->w_wrapline = NULL; - wp->w_dotline = wp->w_markline = 1; - if (bp) - bp->b_nwnd++; - return (wp); -} - -/* - * Reposition dot in the current window to line "n". If the argument is - * positive, it is that line. If it is negative it is that line from the - * bottom. If it is 0 the window is centered (this is what the standard - * redisplay code does). If GOSREC is undefined, default is 0, so it acts - * like GNU. If GOSREC is defined, with no argument it defaults to 1 and - * works like in Gosling. - */ -/* ARGSUSED */ -int -reposition(int f, int n) -{ -#ifndef GOSREC - curwp->w_frame = (f & FFARG) ? (n >= 0 ? n + 1 : n) : 0; -#else /* !GOSREC */ - curwp->w_frame = n; -#endif /* !GOSREC */ - curwp->w_rflag |= WFFRAME; - sgarbf = TRUE; - return (TRUE); -} - -/* - * Refresh the display. A call is made to the "ttresize" entry in the - * terminal handler, which tries to reset "nrow" and "ncol". They will, - * however, never be set outside of the NROW or NCOL range. If the display - * changed size, arrange that everything is redone, then call "update" to - * fix the display. We do this so the new size can be displayed. In the - * normal case the call to "update" in "main.c" refreshes the screen, and - * all of the windows need not be recomputed. This call includes a - * 'force' parameter to ensure that the redraw is done, even after a - * a suspend/continue (where the window size parameters will already - * be updated). Note that when you get to the "display unusable" - * message, the screen will be messed up. If you make the window bigger - * again, and send another command, everything will get fixed! - */ -int -redraw(int f, int n) -{ - return (do_redraw(f, n, FALSE)); -} - -/* ARGSUSED */ -int -do_redraw(int f, int n, int force) -{ - struct mgwin *wp; - int oldnrow, oldncol; - - oldnrow = nrow; - oldncol = ncol; - ttresize(); - if (nrow != oldnrow || ncol != oldncol || force) { - - /* find last */ - wp = wheadp; - while (wp->w_wndp != NULL) - wp = wp->w_wndp; - - /* check if too small */ - if (nrow < wp->w_toprow + 3) { - ewprintf("Display unusable"); - return (FALSE); - } - wp->w_ntrows = nrow - wp->w_toprow - 2; - sgarbf = TRUE; - update(); - } else - sgarbf = TRUE; - return (TRUE); -} - -/* - * The command to make the next window (next => down the screen) the current - * window. There are no real errors, although the command does nothing if - * there is only 1 window on the screen. - */ -/* ARGSUSED */ -int -nextwind(int f, int n) -{ - struct mgwin *wp; - - if ((wp = curwp->w_wndp) == NULL) - wp = wheadp; - curwp = wp; - curbp = wp->w_bufp; - return (TRUE); -} - -/* not in GNU Emacs */ -/* - * This command makes the previous window (previous => up the screen) the - * current window. There are no errors, although the command does not do - * a lot if there is only 1 window. - */ -/* ARGSUSED */ -int -prevwind(int f, int n) -{ - struct mgwin *wp1, *wp2; - - wp1 = wheadp; - wp2 = curwp; - if (wp1 == wp2) - wp2 = NULL; - while (wp1->w_wndp != wp2) - wp1 = wp1->w_wndp; - curwp = wp1; - curbp = wp1->w_bufp; - return (TRUE); -} - -/* - * This command makes the current window the only window on the screen. Try - * to set the framing so that "." does not have to move on the display. Some - * care has to be taken to keep the values of dot and mark in the buffer - * structures right if the destruction of a window makes a buffer become - * undisplayed. - */ -/* ARGSUSED */ -int -onlywind(int f, int n) -{ - struct mgwin *wp; - struct line *lp; - int i; - - while (wheadp != curwp) { - wp = wheadp; - wheadp = wp->w_wndp; - if (--wp->w_bufp->b_nwnd == 0) { - wp->w_bufp->b_dotp = wp->w_dotp; - wp->w_bufp->b_doto = wp->w_doto; - wp->w_bufp->b_markp = wp->w_markp; - wp->w_bufp->b_marko = wp->w_marko; - } - free(wp); - } - while (curwp->w_wndp != NULL) { - wp = curwp->w_wndp; - curwp->w_wndp = wp->w_wndp; - if (--wp->w_bufp->b_nwnd == 0) { - wp->w_bufp->b_dotp = wp->w_dotp; - wp->w_bufp->b_doto = wp->w_doto; - wp->w_bufp->b_markp = wp->w_markp; - wp->w_bufp->b_marko = wp->w_marko; - } - free(wp); - } - lp = curwp->w_linep; - i = curwp->w_toprow; - while (i != 0 && lback(lp) != curbp->b_headp) { - --i; - lp = lback(lp); - } - curwp->w_toprow = 0; - - /* 2 = mode, echo */ - curwp->w_ntrows = nrow - 2; - curwp->w_linep = lp; - curwp->w_rflag |= WFMODE | WFFULL; - return (TRUE); -} - -/* - * Split the current window. A window smaller than 3 lines cannot be split. - * The only other error that is possible is a "malloc" failure allocating the - * structure for the new window. - * If called with a FFOTHARG, flags on the new window are set to 'n'. - */ -/* ARGSUSED */ -int -splitwind(int f, int n) -{ - struct mgwin *wp, *wp1, *wp2; - struct line *lp; - int ntru, ntrd, ntrl; - - if (curwp->w_ntrows < 3) { - ewprintf("Cannot split a %d line window", curwp->w_ntrows); - return (FALSE); - } - wp = new_window(curbp); - if (wp == NULL) { - ewprintf("Unable to create a window"); - return (FALSE); - } - - /* use the current dot and mark */ - wp->w_dotp = curwp->w_dotp; - wp->w_doto = curwp->w_doto; - wp->w_markp = curwp->w_markp; - wp->w_marko = curwp->w_marko; - wp->w_dotline = curwp->w_dotline; - wp->w_markline = curwp->w_markline; - - /* figure out which half of the screen we're in */ - ntru = (curwp->w_ntrows - 1) / 2; /* Upper size */ - ntrl = (curwp->w_ntrows - 1) - ntru; /* Lower size */ - - for (lp = curwp->w_linep, ntrd = 0; lp != curwp->w_dotp; - lp = lforw(lp)) - ntrd++; - - lp = curwp->w_linep; - - /* old is upper window */ - if (ntrd <= ntru) { - /* hit mode line */ - if (ntrd == ntru) - lp = lforw(lp); - curwp->w_ntrows = ntru; - wp->w_wndp = curwp->w_wndp; - curwp->w_wndp = wp; - wp->w_toprow = curwp->w_toprow + ntru + 1; - wp->w_ntrows = ntrl; - /* old is lower window */ - } else { - wp1 = NULL; - wp2 = wheadp; - while (wp2 != curwp) { - wp1 = wp2; - wp2 = wp2->w_wndp; - } - if (wp1 == NULL) - wheadp = wp; - else - wp1->w_wndp = wp; - wp->w_wndp = curwp; - wp->w_toprow = curwp->w_toprow; - wp->w_ntrows = ntru; - - /* mode line */ - ++ntru; - curwp->w_toprow += ntru; - curwp->w_ntrows = ntrl; - while (ntru--) - lp = lforw(lp); - } - - /* adjust the top lines if necessary */ - curwp->w_linep = lp; - wp->w_linep = lp; - - curwp->w_rflag |= WFMODE | WFFULL; - wp->w_rflag |= WFMODE | WFFULL; - /* if FFOTHARG, set flags) */ - if (f & FFOTHARG) - wp->w_flag = n; - - return (TRUE); -} - -/* - * Enlarge the current window. Find the window that loses space. Make sure - * it is big enough. If so, hack the window descriptions, and ask redisplay - * to do all the hard work. You don't just set "force reframe" because dot - * would move. - */ -/* ARGSUSED */ -int -enlargewind(int f, int n) -{ - struct mgwin *adjwp; - struct line *lp; - int i; - - if (n < 0) - return (shrinkwind(f, -n)); - if (wheadp->w_wndp == NULL) { - ewprintf("Only one window"); - return (FALSE); - } - if ((adjwp = curwp->w_wndp) == NULL) { - adjwp = wheadp; - while (adjwp->w_wndp != curwp) - adjwp = adjwp->w_wndp; - } - if (adjwp->w_ntrows <= n) { - ewprintf("Impossible change"); - return (FALSE); - } - - /* shrink below */ - if (curwp->w_wndp == adjwp) { - lp = adjwp->w_linep; - for (i = 0; i < n && lp != adjwp->w_bufp->b_headp; ++i) - lp = lforw(lp); - adjwp->w_linep = lp; - adjwp->w_toprow += n; - /* shrink above */ - } else { - lp = curwp->w_linep; - for (i = 0; i < n && lback(lp) != curbp->b_headp; ++i) - lp = lback(lp); - curwp->w_linep = lp; - curwp->w_toprow -= n; - } - curwp->w_ntrows += n; - adjwp->w_ntrows -= n; - curwp->w_rflag |= WFMODE | WFFULL; - adjwp->w_rflag |= WFMODE | WFFULL; - return (TRUE); -} - -/* - * Shrink the current window. Find the window that gains space. Hack at the - * window descriptions. Ask the redisplay to do all the hard work. - */ -int -shrinkwind(int f, int n) -{ - struct mgwin *adjwp; - struct line *lp; - int i; - - if (n < 0) - return (enlargewind(f, -n)); - if (wheadp->w_wndp == NULL) { - ewprintf("Only one window"); - return (FALSE); - } - /* - * Bit of flakiness - KRANDOM means it was an internal call, and - * to be trusted implicitly about sizes. - */ - if (!(f & FFRAND) && curwp->w_ntrows <= n) { - ewprintf("Impossible change"); - return (FALSE); - } - if ((adjwp = curwp->w_wndp) == NULL) { - adjwp = wheadp; - while (adjwp->w_wndp != curwp) - adjwp = adjwp->w_wndp; - } - - /* grow below */ - if (curwp->w_wndp == adjwp) { - lp = adjwp->w_linep; - for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_headp; ++i) - lp = lback(lp); - adjwp->w_linep = lp; - adjwp->w_toprow -= n; - /* grow above */ - } else { - lp = curwp->w_linep; - for (i = 0; i < n && lp != curbp->b_headp; ++i) - lp = lforw(lp); - curwp->w_linep = lp; - curwp->w_toprow += n; - } - curwp->w_ntrows -= n; - adjwp->w_ntrows += n; - curwp->w_rflag |= WFMODE | WFFULL; - adjwp->w_rflag |= WFMODE | WFFULL; - return (TRUE); -} - -/* - * Delete current window. Call shrink-window to do the screen updating, then - * throw away the window. - */ -/* ARGSUSED */ -int -delwind(int f, int n) -{ - struct mgwin *wp, *nwp; - - wp = curwp; /* Cheap... */ - - /* shrinkwind returning false means only one window... */ - if (shrinkwind(FFRAND, wp->w_ntrows + 1) == FALSE) - return (FALSE); - if (--wp->w_bufp->b_nwnd == 0) { - wp->w_bufp->b_dotp = wp->w_dotp; - wp->w_bufp->b_doto = wp->w_doto; - wp->w_bufp->b_markp = wp->w_markp; - wp->w_bufp->b_marko = wp->w_marko; - } - - /* since shrinkwind did't crap out, we know we have a second window */ - if (wp == wheadp) - wheadp = curwp = wp->w_wndp; - else if ((curwp = wp->w_wndp) == NULL) - curwp = wheadp; - curbp = curwp->w_bufp; - for (nwp = wheadp; nwp != NULL; nwp = nwp->w_wndp) - if (nwp->w_wndp == wp) { - nwp->w_wndp = wp->w_wndp; - break; - } - free(wp); - return (TRUE); -} diff --git a/mg/word.c b/mg/word.c deleted file mode 100644 index c18b620..0000000 --- a/mg/word.c +++ /dev/null @@ -1,346 +0,0 @@ -/* $OpenBSD: word.c,v 1.15 2008/09/15 16:11:35 kjell Exp $ */ - -/* This file is in the public domain. */ - -/* - * Word mode commands. - * The routines in this file implement commands that work word at a time. - * There are all sorts of word mode commands. - */ - -#include "def.h" - -RSIZE countfword(void); - -/* - * Move the cursor backward by "n" words. All of the details of motion are - * performed by the "backchar" and "forwchar" routines. - */ -/* ARGSUSED */ -int -backword(int f, int n) -{ - if (n < 0) - return (forwword(f | FFRAND, -n)); - if (backchar(FFRAND, 1) == FALSE) - return (FALSE); - while (n--) { - while (inword() == FALSE) { - if (backchar(FFRAND, 1) == FALSE) - return (TRUE); - } - while (inword() != FALSE) { - if (backchar(FFRAND, 1) == FALSE) - return (TRUE); - } - } - return (forwchar(FFRAND, 1)); -} - -/* - * Move the cursor forward by the specified number of words. All of the - * motion is done by "forwchar". - */ -/* ARGSUSED */ -int -forwword(int f, int n) -{ - if (n < 0) - return (backword(f | FFRAND, -n)); - while (n--) { - while (inword() == FALSE) { - if (forwchar(FFRAND, 1) == FALSE) - return (TRUE); - } - while (inword() != FALSE) { - if (forwchar(FFRAND, 1) == FALSE) - return (TRUE); - } - } - return (TRUE); -} - -/* - * Move the cursor forward by the specified number of words. As you move, - * convert any characters to upper case. - */ -/* ARGSUSED */ -int -upperword(int f, int n) -{ - int c, s; - RSIZE size; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read-only"); - return (FALSE); - } - - if (n < 0) - return (FALSE); - while (n--) { - while (inword() == FALSE) { - if (forwchar(FFRAND, 1) == FALSE) - return (TRUE); - } - size = countfword(); - undo_add_change(curwp->w_dotp, curwp->w_doto, size); - - while (inword() != FALSE) { - c = lgetc(curwp->w_dotp, curwp->w_doto); - if (ISLOWER(c) != FALSE) { - c = TOUPPER(c); - lputc(curwp->w_dotp, curwp->w_doto, c); - lchange(WFFULL); - } - if (forwchar(FFRAND, 1) == FALSE) - return (TRUE); - } - } - return (TRUE); -} - -/* - * Move the cursor forward by the specified number of words. As you move - * convert characters to lower case. - */ -/* ARGSUSED */ -int -lowerword(int f, int n) -{ - int c, s; - RSIZE size; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read-only"); - return (FALSE); - } - if (n < 0) - return (FALSE); - while (n--) { - while (inword() == FALSE) { - if (forwchar(FFRAND, 1) == FALSE) - return (TRUE); - } - size = countfword(); - undo_add_change(curwp->w_dotp, curwp->w_doto, size); - - while (inword() != FALSE) { - c = lgetc(curwp->w_dotp, curwp->w_doto); - if (ISUPPER(c) != FALSE) { - c = TOLOWER(c); - lputc(curwp->w_dotp, curwp->w_doto, c); - lchange(WFFULL); - } - if (forwchar(FFRAND, 1) == FALSE) - return (TRUE); - } - } - return (TRUE); -} - -/* - * Move the cursor forward by the specified number of words. As you move - * convert the first character of the word to upper case, and subsequent - * characters to lower case. Error if you try to move past the end of the - * buffer. - */ -/* ARGSUSED */ -int -capword(int f, int n) -{ - int c, s; - RSIZE size; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read-only"); - return (FALSE); - } - - if (n < 0) - return (FALSE); - while (n--) { - while (inword() == FALSE) { - if (forwchar(FFRAND, 1) == FALSE) - return (TRUE); - } - size = countfword(); - undo_add_change(curwp->w_dotp, curwp->w_doto, size); - - if (inword() != FALSE) { - c = lgetc(curwp->w_dotp, curwp->w_doto); - if (ISLOWER(c) != FALSE) { - c = TOUPPER(c); - lputc(curwp->w_dotp, curwp->w_doto, c); - lchange(WFFULL); - } - if (forwchar(FFRAND, 1) == FALSE) - return (TRUE); - while (inword() != FALSE) { - c = lgetc(curwp->w_dotp, curwp->w_doto); - if (ISUPPER(c) != FALSE) { - c = TOLOWER(c); - lputc(curwp->w_dotp, curwp->w_doto, c); - lchange(WFFULL); - } - if (forwchar(FFRAND, 1) == FALSE) - return (TRUE); - } - } - } - return (TRUE); -} - -/* - * Count characters in word, from current position - */ -RSIZE -countfword() -{ - RSIZE size; - struct line *dotp; - int doto; - - dotp = curwp->w_dotp; - doto = curwp->w_doto; - size = 0; - - while (inword() != FALSE) { - if (forwchar(FFRAND, 1) == FALSE) - /* hit the end of the buffer */ - goto out; - ++size; - } -out: - curwp->w_dotp = dotp; - curwp->w_doto = doto; - return (size); -} - - -/* - * Kill forward by "n" words. - */ -/* ARGSUSED */ -int -delfword(int f, int n) -{ - RSIZE size; - struct line *dotp; - int doto; - int s; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read-only"); - return (FALSE); - } - if (n < 0) - return (FALSE); - - /* purge kill buffer */ - if ((lastflag & CFKILL) == 0) - kdelete(); - - thisflag |= CFKILL; - dotp = curwp->w_dotp; - doto = curwp->w_doto; - size = 0; - - while (n--) { - while (inword() == FALSE) { - if (forwchar(FFRAND, 1) == FALSE) - /* hit the end of the buffer */ - goto out; - ++size; - } - while (inword() != FALSE) { - if (forwchar(FFRAND, 1) == FALSE) - /* hit the end of the buffer */ - goto out; - ++size; - } - } -out: - curwp->w_dotp = dotp; - curwp->w_doto = doto; - return (ldelete(size, KFORW)); -} - -/* - * Kill backwards by "n" words. The rules for success and failure are now - * different, to prevent strange behavior at the start of the buffer. The - * command only fails if something goes wrong with the actual delete of the - * characters. It is successful even if no characters are deleted, or if you - * say delete 5 words, and there are only 4 words left. I considered making - * the first call to "backchar" special, but decided that that would just be - * weird. Normally this is bound to "M-Rubout" and to "M-Backspace". - */ -/* ARGSUSED */ -int -delbword(int f, int n) -{ - RSIZE size; - int s; - - if ((s = checkdirty(curbp)) != TRUE) - return (s); - if (curbp->b_flag & BFREADONLY) { - ewprintf("Buffer is read-only"); - return (FALSE); - } - - if (n < 0) - return (FALSE); - - /* purge kill buffer */ - if ((lastflag & CFKILL) == 0) - kdelete(); - thisflag |= CFKILL; - if (backchar(FFRAND, 1) == FALSE) - /* hit buffer start */ - return (TRUE); - - /* one deleted */ - size = 1; - while (n--) { - while (inword() == FALSE) { - if (backchar(FFRAND, 1) == FALSE) - /* hit buffer start */ - goto out; - ++size; - } - while (inword() != FALSE) { - if (backchar(FFRAND, 1) == FALSE) - /* hit buffer start */ - goto out; - ++size; - } - } - if (forwchar(FFRAND, 1) == FALSE) - return (FALSE); - - /* undo assumed delete */ - --size; -out: - return (ldelete(size, KBACK)); -} - -/* - * Return TRUE if the character at dot is a character that is considered to be - * part of a word. The word character list is hard coded. Should be settable. - */ -int -inword(void) -{ - /* can't use lgetc in ISWORD due to bug in OSK cpp */ - return (curwp->w_doto != llength(curwp->w_dotp) && - ISWORD(curwp->w_dotp->l_text[curwp->w_doto])); -} diff --git a/mg/yank.c b/mg/yank.c deleted file mode 100644 index d408286..0000000 --- a/mg/yank.c +++ /dev/null @@ -1,264 +0,0 @@ -/* $OpenBSD: yank.c,v 1.10 2011/07/15 16:50:52 deraadt Exp $ */ - -/* This file is in the public domain. */ - -/* - * kill ring functions - */ - -#include "def.h" - -#include - -#ifndef KBLOCK -#define KBLOCK 256 /* Kill buffer block size. */ -#endif - -static char *kbufp = NULL; /* Kill buffer data. */ -static RSIZE kused = 0; /* # of bytes used in KB. */ -static RSIZE ksize = 0; /* # of bytes allocated in KB. */ -static RSIZE kstart = 0; /* # of first used byte in KB. */ - -static int kgrow(int); - -/* - * Delete all of the text saved in the kill buffer. Called by commands when - * a new kill context is created. The kill buffer array is released, just in - * case the buffer has grown to an immense size. No errors. - */ -void -kdelete(void) -{ - if (kbufp != NULL) { - free(kbufp); - kbufp = NULL; - kstart = kused = ksize = 0; - } -} - -/* - * Insert a character to the kill buffer, enlarging the buffer if there - * isn't any room. Always grow the buffer in chunks, on the assumption - * that if you put something in the kill buffer you are going to put more - * stuff there too later. Return TRUE if all is well, and FALSE on errors. - * Print a message on errors. Dir says whether to put it at back or front. - * This call is ignored if KNONE is set. - */ -int -kinsert(int c, int dir) -{ - if (dir == KNONE) - return (TRUE); - if (kused == ksize && dir == KFORW && kgrow(dir) == FALSE) - return (FALSE); - if (kstart == 0 && dir == KBACK && kgrow(dir) == FALSE) - return (FALSE); - if (dir == KFORW) - kbufp[kused++] = c; - else if (dir == KBACK) - kbufp[--kstart] = c; - else - panic("broken kinsert call"); /* Oh shit! */ - return (TRUE); -} - -/* - * kgrow - just get more kill buffer for the callee. If dir = KBACK - * we are trying to get space at the beginning of the kill buffer. - */ -static int -kgrow(int dir) -{ - int nstart; - char *nbufp; - - if ((unsigned)(ksize + KBLOCK) <= (unsigned)ksize) { - /* probably 16 bit unsigned */ - ewprintf("Kill buffer size at maximum"); - return (FALSE); - } - if ((nbufp = malloc((unsigned)(ksize + KBLOCK))) == NULL) { - ewprintf("Can't get %ld bytes", (long)(ksize + KBLOCK)); - return (FALSE); - } - nstart = (dir == KBACK) ? (kstart + KBLOCK) : (KBLOCK / 4); - bcopy(&(kbufp[kstart]), &(nbufp[nstart]), (int)(kused - kstart)); - if (kbufp != NULL) - free(kbufp); - kbufp = nbufp; - ksize += KBLOCK; - kused = kused - kstart + nstart; - kstart = nstart; - return (TRUE); -} - -/* - * This function gets characters from the kill buffer. If the character - * index "n" is off the end, it returns "-1". This lets the caller just - * scan along until it gets a "-1" back. - */ -int -kremove(int n) -{ - if (n < 0 || n + kstart >= kused) - return (-1); - return (CHARMASK(kbufp[n + kstart])); -} - -/* - * Copy a string into the kill buffer. kflag gives direction. - * if KNONE, do nothing. - */ -int -kchunk(char *cp1, RSIZE chunk, int kflag) -{ - /* - * HACK - doesn't matter, and fixes back-over-nl bug for empty - * kill buffers. - */ - if (kused == kstart) - kflag = KFORW; - - if (kflag & KFORW) { - while (ksize - kused < chunk) - if (kgrow(kflag) == FALSE) - return (FALSE); - bcopy(cp1, &(kbufp[kused]), (int)chunk); - kused += chunk; - } else if (kflag & KBACK) { - while (kstart < chunk) - if (kgrow(kflag) == FALSE) - return (FALSE); - bcopy(cp1, &(kbufp[kstart - chunk]), (int)chunk); - kstart -= chunk; - } - - return (TRUE); -} - -/* - * Kill line. If called without an argument, it kills from dot to the end - * of the line, unless it is at the end of the line, when it kills the - * newline. If called with an argument of 0, it kills from the start of the - * line to dot. If called with a positive argument, it kills from dot - * forward over that number of newlines. If called with a negative argument - * it kills any text before dot on the current line, then it kills back - * abs(arg) lines. - */ -/* ARGSUSED */ -int -killline(int f, int n) -{ - struct line *nextp; - RSIZE chunk; - int i, c; - - /* clear kill buffer if last wasn't a kill */ - if ((lastflag & CFKILL) == 0) - kdelete(); - thisflag |= CFKILL; - if (!(f & FFARG)) { - for (i = curwp->w_doto; i < llength(curwp->w_dotp); ++i) - if ((c = lgetc(curwp->w_dotp, i)) != ' ' && c != '\t') - break; - if (i == llength(curwp->w_dotp)) - chunk = llength(curwp->w_dotp) - curwp->w_doto + 1; - else { - chunk = llength(curwp->w_dotp) - curwp->w_doto; - if (chunk == 0) - chunk = 1; - } - } else if (n > 0) { - chunk = llength(curwp->w_dotp) - curwp->w_doto; - nextp = lforw(curwp->w_dotp); - if (nextp != curbp->b_headp) - chunk++; /* newline */ - if (nextp == curbp->b_headp) - goto done; /* EOL */ - i = n; - while (--i) { - chunk += llength(nextp); - nextp = lforw(nextp); - if (nextp != curbp->b_headp) - chunk++; /* newline */ - if (nextp == curbp->b_headp) - break; /* EOL */ - } - } else { - /* n <= 0 */ - chunk = curwp->w_doto; - curwp->w_doto = 0; - i = n; - while (i++) { - if (lforw(curwp->w_dotp)) - chunk++; - curwp->w_dotp = lback(curwp->w_dotp); - curwp->w_rflag |= WFMOVE; - chunk += llength(curwp->w_dotp); - } - } - /* - * KFORW here is a bug. Should be KBACK/KFORW, but we need to - * rewrite the ldelete code (later)? - */ -done: - if (chunk) - return (ldelete(chunk, KFORW)); - return (TRUE); -} - -/* - * Yank text back from the kill buffer. This is really easy. All of the work - * is done by the standard insert routines. All you do is run the loop, and - * check for errors. The blank lines are inserted with a call to "newline" - * instead of a call to "lnewline" so that the magic stuff that happens when - * you type a carriage return also happens when a carriage return is yanked - * back from the kill buffer. An attempt has been made to fix the cosmetic - * bug associated with a yank when dot is on the top line of the window - * (nothing moves, because all of the new text landed off screen). - */ -/* ARGSUSED */ -int -yank(int f, int n) -{ - struct line *lp; - int c, i, nline; - - if (n < 0) - return (FALSE); - - /* newline counting */ - nline = 0; - - undo_boundary_enable(FFRAND, 0); - while (n--) { - /* mark around last yank */ - isetmark(); - i = 0; - while ((c = kremove(i)) >= 0) { - if (c == '\n') { - if (newline(FFRAND, 1) == FALSE) - return (FALSE); - ++nline; - } else { - if (linsert(1, c) == FALSE) - return (FALSE); - } - ++i; - } - } - /* cosmetic adjustment */ - lp = curwp->w_linep; - - /* if offscreen insert */ - if (curwp->w_dotp == lp) { - while (nline-- && lback(lp) != curbp->b_headp) - lp = lback(lp); - /* adjust framing */ - curwp->w_linep = lp; - curwp->w_rflag |= WFFULL; - } - undo_boundary_enable(FFRAND, 1); - return (TRUE); -} - diff --git a/pd_readline.c b/pd_readline.c index 168a860..5bf04dc 100644 --- a/pd_readline.c +++ b/pd_readline.c @@ -1,183 +1,259 @@ - - -/* pd_readline.c */ -/* Status (as at 26th Aug 2012) : useful progress. */ -/* Keystroke sequences (along with the special flags */ -/* like Esc, Ctrl, Alt etc are now stored in a buffer */ -/* ( an array of structs ). */ -/* It will still be some time before this is a REAL */ -/* readline, but we are "on the way"...... */ -/* This code is released to the public domain. */ -/* "Share and enjoy...." ;) */ - - -#include -#include -#include /* For getch() */ - -/* This implementation of getch() is from here - */ -/* http://wesley.vidiqatch.org/ */ -/* Thanks, Wesley! */ -static struct termios old, new; - -/* Initialize new terminal i/o settings */ -void initTermios(int echo) { - tcgetattr(0, &old); /* grab old terminal i/o settings */ - new = old; /* make new settings same as old settings */ - new.c_lflag &= ~ICANON; /* disable buffered i/o */ - new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ - tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ -} - - -/* Restore old terminal i/o settings */ -void resetTermios(void) { - tcsetattr(0, TCSANOW, &old); -} - - -/* Read 1 character - echo defines echo mode */ -char getch_(int echo) { - char ch; - initTermios(echo); - ch = getchar(); - resetTermios(); - return ch; -} - - -/* Read 1 character without echo */ -char getch(void) { - return getch_(0); -} - - -/* Read 1 character with echo */ -char getche(void) { - return getch_(1); -} - - - -/* Helper function, to let us see if a .history file */ -/* exists in the current directory. */ -int fexists(char *fname) -{ - - FILE *fptr ; - - fptr = fopen(fname, "r") ; - - if ( !fptr ) return -1 ; /* File does not exist in dir. */ - - fclose(fptr); - return 0; /* File DOES exist in dir. */ - -} - - - /* Struct to store key sequences */ -typedef struct { - int fnkey; - int ctrl; - int alt ; - int shf ; - int esc ; - int lbr ; /* For left-bracket ([) of escape sequences */ - int key; - } keyseq ; - - - - - -int main(void) -{ - - printf("Public Domain Readline \n"); - printf("NOTE! - at the moment, we are using \n"); - printf("NON-echoing reads, storing the keystrokes \n"); - printf("in a buffer \n"); - - - /* Buffer - an array of keyseq structs. */ - /* Note - now that we store the keystrokes in here, */ - /* we can look at the various flags and decide whether to */ - /* "echo" the key (as normal) or suppress it (as with an */ - /* arrow key). */ - keyseq buffer[80] ; - - /* Buffer "pointer" */ - int bufpnt = 0; - - - /* Test for existence of history file. */ - int exists; - exists = fexists(".history"); - printf("Result: %d \n", exists); - - while(1) - { - - int key = getch(); - - /* Printable chars. */ - if ( (key >= 32) && (key <= 126) ) - { - buffer[bufpnt].key = key; - bufpnt += 1; - } - - /* Up arrow is 27, 91, 65. ( ESC [ A ) */ - /* Down arrow is 27, 91, 66. ( ESC [ B ) */ - /* Right arrow is 27, 91, 67. ( ESC [ C ) */ - /* Left arrow is 27, 91, 68. ( ESC [ D ) */ - /* Function keys. */ - /* F2 is 27, 79, 81. */ - /* F3 is 27, 79, 82. */ - /* F4 is 27, 79, 83. */ - - - else if(key == 27) - { - - buffer[bufpnt].esc = 1; - key = getch(); - if(key == 91) - buffer[bufpnt].lbr = 1; - key = getch(); - if( (key >= 65) && (key <= 68) ) - { - buffer[bufpnt].key = key; - } - bufpnt += 1; - } - - - - /* The Enter key exits. Enter is 10 decimal */ - else if(key == 10) - { - int j ; - /* Print the array of structs. */ - for (j=0; j<10; j++) - { - printf("Fnkey: %d ", buffer[j].fnkey ) ; - printf("Ctrl: %d ", buffer[j].ctrl ) ; - printf("Alt: %d ", buffer[j].alt ) ; - printf("Shf: %d ", buffer[j].shf ) ; - printf("Esc: %d ", buffer[j].esc ) ; - printf("Lbr: %d ", buffer[j].lbr ) ; - printf("Key: %d \n", buffer[j].key ) ; - } - - break; - } /* Key = Enter */ - } - - return 0; -} - - - - + + +/* pd_readline.c */ +/* Some code to allow the editing of a command-line. */ +/* You can also move around with the left and right */ +/* arrow keys, and recall previous commands with the */ +/* up-arrow key. */ +/* This code is released to the public domain. */ +/* "Share and enjoy...." ;) */ + + + +#include +#include +#include + +/* This implementation of getch() is from here - */ +/* http://wesley.vidiqatch.org/ */ +/* Thanks, Wesley! */ +static struct termios old, new; + +/* Initialize new terminal i/o settings */ +void initTermios(int echo) { + tcgetattr(0, &old); /* grab old terminal i/o settings */ + new = old; /* make new settings same as old settings */ + new.c_lflag &= ~ICANON; /* disable buffered i/o */ + new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ + tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ +} + + +/* Restore old terminal i/o settings */ +void resetTermios(void) { + tcsetattr(0, TCSANOW, &old); +} + + +/* Read 1 character - echo defines echo mode */ +char getch_(int echo) { + char ch; + initTermios(echo); + ch = getchar(); + resetTermios(); + return ch; +} + + +/* Read 1 character without echo */ +char getch(void) { + return getch_(0); +} + + +/* Read 1 character with echo */ +char getche(void) { + return getch_(1); +} + + + +/* Helper function, to let us see if a file */ +/* exists in the current directory. */ +int fexists(char *fname) +{ + FILE *fptr; + fptr = fopen(fname, "r") ; + if ( !fptr ) return -1 ; /* File does not exist in dir. */ + fclose(fptr); + return 0; /* File DOES exist in dir. */ +} + + +/* Helper function to chop newlines off the lines read in. */ +/* Without this being done, an extra newline is inserted */ +/* (which is usually not what is wanted). */ +char *chop(char *s) +{ + s[strcspn(s,"\n")] = '\0'; + return s; +} + + +/* An array to store the command-history file in. */ +/* Only 20 lines are read. */ +char hist[20][80]; + + +/* Read the file into the array of strings. */ +void readfile(char *fname) +{ + int retval = fexists(fname); + + int i; + if (retval == 0) { + /* File exists, so open it. */ + /* We open it in read-write mode so we can */ + /* append new commands to it. */ + FILE *fptr; + fptr = fopen(fname, "rw"); + + for(i=0; i<20; i++) + { + chop(fgets(hist[i], 80, fptr) ); + } + + } /* retval == 0 */ + + else puts("Error! File does not exist. \n"); + +} + + +/* Helper function to print the command-history file. */ +void printfile(void) +{ + int j; + + for(j=0; j<20; j++) + { + puts(hist[j]); + } +} + + + + +/* Helper function. Print a previous command-line WITHOUT */ +/* a newline. */ +void putline(char *str) +{ + char *line = chop(str); + printf("%s", line); +} + + + + +int main(void) +{ + +/* Our "command-history" file. */ +readfile("test.txt"); + +/* Main buffer for the command-line. */ +char buffer[80]; + +/* Main buffer "pointer" */ +int bufpnt = 0; + +/* "Pointer" for the history file. */ +int histpnt = 20; + + + while(1) + { + + int key = getch(); + buffer[bufpnt] = key; + bufpnt += 1; + + /* Printable chars. */ + if ( (key >= 32) && (key <= 126) ) + { + /* We have a printable key so print it. */ + putchar(key); + bufpnt += 1; + } + + /* Up arrow is 27, 91, 65. ( ESC [ A ) */ + /* Down arrow is 27, 91, 66. ( ESC [ B ) */ + /* Right arrow is 27, 91, 67. ( ESC [ C ) */ + /* Left arrow is 27, 91, 68. ( ESC [ D ) */ + /* Function keys. */ + /* F2 is 27, 79, 81. */ + /* F3 is 27, 79, 82. */ + /* F4 is 27, 79, 83. */ + + /* Backspace */ + else if(key == 127) + { + /* Move left 1 char and delete that char */ + bufpnt -= 1; + printf("\033[1D"); + printf("\040"); + printf("\033[1D"); + /* Move 1 char to left again */ + bufpnt -= 1; + } + + /* We have an escape key-sequence */ + else if(key == 27) + { + key = getch(); + if(key == 91) + key = getch(); + + if (key == 65) /* Up Arrow */ + { + /* Move one command "back" in history. */ + histpnt -= 1; + /* Clear to end of line. */ + printf("\033[80D"); + printf("\033[K"); + /* Move buffer pointer to start of line */ + bufpnt = 0; + /* Clear the array. */ + memset(buffer, 0, sizeof(char)*80); + /* Print the pointed-at command-sequence. */ + putline(hist[histpnt]); + } + + if(key == 66) /* Down Arrow */ + { + /* Move one command "forward" in history. */ + histpnt += 1; + /* Clear to end of line. */ + printf("\033[80D"); + printf("\033[K"); + /* Move buffer pointer to start of line */ + bufpnt = 0; + /* Clear the array. */ + memset(buffer, 0, sizeof(char)*80); + /* Print the pointed-at command-sequence. */ + putline(hist[histpnt]); + } + + if(key == 67) /* Left arrow */ + { + /* Move one character to the left. */ + printf("\033[1C"); + } + + if(key == 68) /* Right arrow */ + { + /* Move one character to the right. */ + printf("\033[1D"); + } + + } /* End of key=27 key sequence. */ + + + /* The Enter key exits. Enter is 10 decimal */ + else if(key == 10) + { + puts("\n"); + puts("Exiting... \n"); + break; + } /* Key = Enter */ + } + + return 0; + +} + + + + + + diff --git a/pd_readline2.c b/pd_readline2.c deleted file mode 100644 index 63a31e7..0000000 --- a/pd_readline2.c +++ /dev/null @@ -1,212 +0,0 @@ - - -/* pd_readline2.c */ -/* Status (as at 26th Aug 2012) : useful progress. */ -/* Keystroke sequences (along with the special flags */ -/* like Esc, Ctrl, Alt etc are now stored in a buffer */ -/* ( an array of structs ). */ - -/* The code can now distinguish between a printable key */ -/* and a key that should not be printed. */ - -/* Backspace key, and left and right arrow keys now work. */ - -/* It will still be some time before this is a REAL */ -/* readline, but we are "on the way"...... */ -/* This code is released to the public domain. */ -/* "Share and enjoy...." ;) */ - - -#include -#include -#include /* For getch() */ - -/* This implementation of getch() is from here - */ -/* http://wesley.vidiqatch.org/ */ -/* Thanks, Wesley! */ -static struct termios old, new; - -/* Initialize new terminal i/o settings */ -void initTermios(int echo) { - tcgetattr(0, &old); /* grab old terminal i/o settings */ - new = old; /* make new settings same as old settings */ - new.c_lflag &= ~ICANON; /* disable buffered i/o */ - new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ - tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ -} - - -/* Restore old terminal i/o settings */ -void resetTermios(void) { - tcsetattr(0, TCSANOW, &old); -} - - -/* Read 1 character - echo defines echo mode */ -char getch_(int echo) { - char ch; - initTermios(echo); - ch = getchar(); - resetTermios(); - return ch; -} - - -/* Read 1 character without echo */ -char getch(void) { - return getch_(0); -} - - -/* Read 1 character with echo */ -char getche(void) { - return getch_(1); -} - - - -/* Helper function, to let us see if a .history file */ -/* exists in the current directory. */ -int fexists(char *fname) -{ - - FILE *fptr ; - - fptr = fopen(fname, "r") ; - - if ( !fptr ) return -1 ; /* File does not exist in dir. */ - - fclose(fptr); - return 0; /* File DOES exist in dir. */ - -} - - - /* Struct to store key sequences */ -typedef struct { - int fnkey; - int ctrl; - int alt ; - int shf ; - int esc ; - int lbr ; /* For left-bracket ([) of escape sequences */ - int key; - } keyseq ; - - - - - -int main(void) -{ - - printf("Public Domain Readline \n"); - - /* Buffer - an array of keyseq structs. */ - /* Note - now that we store the keystrokes in here, */ - /* we can look at the various flags and decide whether to */ - /* "echo" the key (as normal) or suppress it (as with an */ - /* arrow key). */ - keyseq buffer[80] ; - - /* Buffer "pointer" */ - int bufpnt = 0; - - - /* Test for existence of history file. */ - int exists; - exists = fexists(".history"); - printf("Result: %d \n", exists); - - while(1) - { - - int key = getch(); - - /* Printable chars. */ - if ( (key >= 32) && (key <= 126) ) - { - /* We have a printable key so print it. */ - putchar(key); - buffer[bufpnt].key = key; - bufpnt += 1; - } - - /* Up arrow is 27, 91, 65. ( ESC [ A ) */ - /* Down arrow is 27, 91, 66. ( ESC [ B ) */ - /* Right arrow is 27, 91, 67. ( ESC [ C ) */ - /* Left arrow is 27, 91, 68. ( ESC [ D ) */ - /* Function keys. */ - /* F2 is 27, 79, 81. */ - /* F3 is 27, 79, 82. */ - /* F4 is 27, 79, 83. */ - - /* Backspace */ - else if(key == 127) - { - buffer[bufpnt].key = key; - /* Move 1 char to left */ - printf("\033[1D"); - printf("\040"); - printf("\033[1D"); - bufpnt += 1; - } - - else if(key == 27) - { - buffer[bufpnt].esc = 1; - key = getch(); - if(key == 91) - buffer[bufpnt].lbr = 1; - key = getch(); - if(key == 65) /* Up arrow */ - { - buffer[bufpnt].key = key; - } - if(key == 66) /* Down arrow */ - { - buffer[bufpnt].key = key; - } - if(key == 67) /* Left arrow */ - { - buffer[bufpnt].key = key; - printf("\033[1C"); - } - if(key == 68) /* Right arrow */ - { - buffer[bufpnt].key = key; - printf("\033[1D"); - } - - bufpnt += 1; - } - - - - /* The Enter key exits. Enter is 10 decimal */ - else if(key == 10) - { - puts("\n"); - int j ; - /* Print the array of structs. */ - for (j=0; j -#include -#include /* For getch() */ - -/* This implementation of getch() is from here - */ -/* http://wesley.vidiqatch.org/ */ -/* Thanks, Wesley! */ -static struct termios old, new; - -/* Initialize new terminal i/o settings */ -void initTermios(int echo) { - tcgetattr(0, &old); /* grab old terminal i/o settings */ - new = old; /* make new settings same as old settings */ - new.c_lflag &= ~ICANON; /* disable buffered i/o */ - new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ - tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ -} - - -/* Restore old terminal i/o settings */ -void resetTermios(void) { - tcsetattr(0, TCSANOW, &old); -} - - -/* Read 1 character - echo defines echo mode */ -char getch_(int echo) { - char ch; - initTermios(echo); - ch = getchar(); - resetTermios(); - return ch; -} - - -/* Read 1 character without echo */ -char getch(void) { - return getch_(0); -} - - -/* Read 1 character with echo */ -char getche(void) { - return getch_(1); -} - - - - -int main(void) -{ - - printf("Public Domain Menu Program \n"); - printf("\nUse the up and down arrow keys then press Enter\n"); - - int menunum = 0; - - while(1) - { - - int key = getch(); - - /* Up arrow is 27, 91, 65. ( ESC [ A ) */ - /* Down arrow is 27, 91, 66. ( ESC [ B ) */ - /* Right arrow is 27, 91, 67. ( ESC [ C ) */ - /* Left arrow is 27, 91, 68. ( ESC [ D ) */ - if(key == 27) - { key = getch(); - if(key == 91) - key = getch(); - if(key == 65) - { puts("You pressed up arrow! \n"); - menunum-=1; - printf("Menunum is now %d \n", menunum); - } - else if(key == 66) - { puts("You pressed down arrow! \n"); - menunum+=1; - printf("Menunum is now %d \n", menunum); - } - else if(key == 67) - { puts("You pressed right arrow! \n"); - } - else if(key == 68) - { puts("You pressed left arrow! \n"); - } - } - - /* A few other keys (for testing purposes ) */ - else if(key == 97) - { puts("You pressed the \"a\" key! \n"); - } - else if(key == 98) - { puts("You pressed the \"b\" key! \n"); - } - else if(key == 99) - { puts("You pressed the \"c\" key! \n"); - } - else if(key == 100) - { puts("You pressed the \"d\" key! \n"); - } - - - /* The Enter key exits. Enter is 10 decimal */ - else if(key == 10) - { printf("You pressed ENTER! You chose item %d \n", menunum); - break; } - } - - return 0; -} - - - - diff --git a/pdmenu2.c b/pdmenu2.c deleted file mode 100644 index 746eb31..0000000 --- a/pdmenu2.c +++ /dev/null @@ -1,170 +0,0 @@ - - -/* pdmenu.c */ -/* This code is aimed at helping those who would like to */ -/* create menus without using the curses library. */ -/* It creates a count variable (which could be used to */ -/* keep track of which item is highlighted). Using the */ -/* up and down arrow keys increments and decrements the */ -/* count variable. Finally, when you press Enter, the */ -/* value of the count variable is printed and the program */ -/* exits. */ -/* This code is released to the public domain. */ -/* "Share and enjoy...." ;) */ - - -#include -#include -#include /* For getch() */ - -/* This implementation of getch() is from here - */ -/* http://wesley.vidiqatch.org/ */ -/* Thanks, Wesley! */ -static struct termios old, new; - -/* Initialize new terminal i/o settings */ -void initTermios(int echo) { - tcgetattr(0, &old); /* grab old terminal i/o settings */ - new = old; /* make new settings same as old settings */ - new.c_lflag &= ~ICANON; /* disable buffered i/o */ - new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ - tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ -} - - -/* Restore old terminal i/o settings */ -void resetTermios(void) { - tcsetattr(0, TCSANOW, &old); -} - - -/* Read 1 character - echo defines echo mode */ -char getch_(int echo) { - char ch; - initTermios(echo); - ch = getchar(); - resetTermios(); - return ch; -} - - -/* Read 1 character without echo */ -char getch(void) { - return getch_(0); -} - - -/* Read 1 character with echo */ -char getche(void) { - return getch_(1); -} - - - -/* Helper function, to let us see if a .history file */ -/* exists in the current directory. */ -int fexists(char *fname) -{ - - FILE *fptr ; - - fptr = fopen(fname, "r") ; - - if ( !fptr ) return -1 ; /* File does not exist in dir. */ - - fclose(fptr); - return 0; /* File DOES exist in dir. */ - -} - - - -int main(void) -{ - - printf("Public Domain Menu Program \n"); - printf("\nUse the up and down arrow keys then press Enter\n"); - - int menunum = 0; - - /* Buffer */ - char buffer[80] ; - - /* Buffer "pointer" */ - int bufpnt = 0; - - - /* Test for existence of history file. */ - int exists; - exists = fexists(".history"); - printf("Result: %d \n", exists); - - while(1) - { - - int key = getch(); - - /* Printable chars. */ - if ( (key >= 32) && (key <= 126) ) - { - buffer[bufpnt] = key; - bufpnt += 1; - } - - /* Up arrow is 27, 91, 65. ( ESC [ A ) */ - /* Down arrow is 27, 91, 66. ( ESC [ B ) */ - /* Right arrow is 27, 91, 67. ( ESC [ C ) */ - /* Left arrow is 27, 91, 68. ( ESC [ D ) */ - else if(key == 27) - { key = getch(); - if(key == 91) - key = getch(); - if(key == 65) - { puts("You pressed up arrow! \n"); - menunum-=1; - printf("Menunum is now %d \n", menunum); - } - else if(key == 66) - { puts("You pressed down arrow! \n"); - menunum+=1; - printf("Menunum is now %d \n", menunum); - } - else if(key == 67) - { puts("You pressed right arrow! \n"); - } - else if(key == 68) - { puts("You pressed left arrow! \n"); - } - } - - /* A few other keys (for testing purposes ) */ - - /* - else if(key == 97) - { puts("You pressed the \"a\" key! \n"); - } - else if(key == 98) - { puts("You pressed the \"b\" key! \n"); - } - else if(key == 99) - { puts("You pressed the \"c\" key! \n"); - } - else if(key == 100) - { puts("You pressed the \"d\" key! \n"); - } - */ - - - /* The Enter key exits. Enter is 10 decimal */ - else if(key == 10) - { printf("You pressed ENTER! You chose item %d \n", menunum); - printf("Buffer is %s \n", buffer) ; - break; } - } - - return 0; -} - - - - diff --git a/pdmenu3.c b/pdmenu3.c deleted file mode 100644 index 6da1936..0000000 --- a/pdmenu3.c +++ /dev/null @@ -1,186 +0,0 @@ - - -/* pdmenu.c */ -/* This code is aimed at helping those who would like to */ -/* create menus without using the curses library. */ -/* It creates a count variable (which could be used to */ -/* keep track of which item is highlighted). Using the */ -/* up and down arrow keys increments and decrements the */ -/* count variable. Finally, when you press Enter, the */ -/* value of the count variable is printed and the program */ -/* exits. */ -/* This code is released to the public domain. */ -/* "Share and enjoy...." ;) */ - - -#include -#include -#include /* For getch() */ - -/* This implementation of getch() is from here - */ -/* http://wesley.vidiqatch.org/ */ -/* Thanks, Wesley! */ -static struct termios old, new; - -/* Initialize new terminal i/o settings */ -void initTermios(int echo) { - tcgetattr(0, &old); /* grab old terminal i/o settings */ - new = old; /* make new settings same as old settings */ - new.c_lflag &= ~ICANON; /* disable buffered i/o */ - new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ - tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ -} - - -/* Restore old terminal i/o settings */ -void resetTermios(void) { - tcsetattr(0, TCSANOW, &old); -} - - -/* Read 1 character - echo defines echo mode */ -char getch_(int echo) { - char ch; - initTermios(echo); - ch = getchar(); - resetTermios(); - return ch; -} - - -/* Read 1 character without echo */ -char getch(void) { - return getch_(0); -} - - -/* Read 1 character with echo */ -char getche(void) { - return getch_(1); -} - - - -/* Helper function, to let us see if a .history file */ -/* exists in the current directory. */ -int fexists(char *fname) -{ - - FILE *fptr ; - - fptr = fopen(fname, "r") ; - - if ( !fptr ) return -1 ; /* File does not exist in dir. */ - - fclose(fptr); - return 0; /* File DOES exist in dir. */ - -} - - - /* Struct to store key sequences */ -typedef struct { - int fnkey; - int ctrl; - int alt ; - int shf ; - int esc ; - int lbr ; /* For left-bracket ([) of escape sequences */ - int key; - } keyseq ; - - - - - -int main(void) -{ - - printf("Public Domain Menu Program \n"); - - - keyseq myseq; - - - /* Buffer */ - keyseq buffer[80] ; - - /* Buffer "pointer" */ - int bufpnt = 0; - - - /* Test for existence of history file. */ - int exists; - exists = fexists(".history"); - printf("Result: %d \n", exists); - - while(1) - { - - int key = getch(); - - /* Printable chars. */ - if ( (key >= 32) && (key <= 126) ) - { - myseq.key = key; - buffer[bufpnt] = myseq; - bufpnt += 1; - } - - /* Up arrow is 27, 91, 65. ( ESC [ A ) */ - /* Down arrow is 27, 91, 66. ( ESC [ B ) */ - /* Right arrow is 27, 91, 67. ( ESC [ C ) */ - /* Left arrow is 27, 91, 68. ( ESC [ D ) */ - /* Function keys. */ - /* F2 is 27, 79, 81. */ - /* F3 is 27, 79, 82. */ - /* F4 is 27, 79, 83. */ - - - else if(key == 27) - { - myseq.key = key; - buffer[bufpnt] = myseq; - bufpnt += 1; - key = getch(); - if(key == 91) - myseq.key = key; - buffer[bufpnt] = myseq; - bufpnt += 1; - key = getch(); - if( (key >= 65) && (key <= 68) ) - { - myseq.key = key; - buffer[bufpnt] = myseq; - bufpnt += 1; - } - } - - - - /* The Enter key exits. Enter is 10 decimal */ - else if(key == 10) - { - int j ; - /* Print the array of structs. */ - for (j=0; j<10; j++) - { - printf("Fnkey: %d ", buffer[j].fnkey ) ; - printf("Ctrl: %d ", buffer[j].ctrl ) ; - printf("Alt: %d ", buffer[j].alt ) ; - printf("Shf: %d ", buffer[j].shf ) ; - printf("Esc: %d ", buffer[j].esc ) ; - printf("Lbr: %d ", buffer[j].lbr ) ; - printf("Key: %d \n", buffer[j].key ) ; - } - - break; - } /* Key = Enter */ - } - - return 0; -} - - - - diff --git a/pdmenu4.c b/pdmenu4.c deleted file mode 100644 index c8bff2e..0000000 --- a/pdmenu4.c +++ /dev/null @@ -1,185 +0,0 @@ - - -/* pd_readline.c */ -/* Status (as at 26th Aug 2012) : useful progress. */ -/* Keystroke sequences (along with the special flags */ -/* like Esc, Ctrl, Alt etc are now stored in a buffer */ -/* ( an array of structs ). */ -/* It will still be some time before this is a REAL */ -/* readline, but we are "on the way"...... */ -/* This code is released to the public domain. */ -/* "Share and enjoy...." ;) */ - - -#include -#include -#include /* For getch() */ - -/* This implementation of getch() is from here - */ -/* http://wesley.vidiqatch.org/ */ -/* Thanks, Wesley! */ -static struct termios old, new; - -/* Initialize new terminal i/o settings */ -void initTermios(int echo) { - tcgetattr(0, &old); /* grab old terminal i/o settings */ - new = old; /* make new settings same as old settings */ - new.c_lflag &= ~ICANON; /* disable buffered i/o */ - new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ - tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ -} - - -/* Restore old terminal i/o settings */ -void resetTermios(void) { - tcsetattr(0, TCSANOW, &old); -} - - -/* Read 1 character - echo defines echo mode */ -char getch_(int echo) { - char ch; - initTermios(echo); - ch = getchar(); - resetTermios(); - return ch; -} - - -/* Read 1 character without echo */ -char getch(void) { - return getch_(0); -} - - -/* Read 1 character with echo */ -char getche(void) { - return getch_(1); -} - - - -/* Helper function, to let us see if a .history file */ -/* exists in the current directory. */ -int fexists(char *fname) -{ - - FILE *fptr ; - - fptr = fopen(fname, "r") ; - - if ( !fptr ) return -1 ; /* File does not exist in dir. */ - - fclose(fptr); - return 0; /* File DOES exist in dir. */ - -} - - - /* Struct to store key sequences */ -typedef struct { - int fnkey; - int ctrl; - int alt ; - int shf ; - int esc ; - int lbr ; /* For left-bracket ([) of escape sequences */ - int key; - } keyseq ; - - - - - -int main(void) -{ - - printf("Public Domain Readline \n"); - printf("NOTE! - at the moment, we are using \n"); - printf("NON-echoing reads, storing the keystrokes \n"); - printf("in a buffer \n"); - - - /* Buffer - an array of keyseq structs. */ - /* Note - now that we store the keystrokes in here, */ - /* we can look at the various flags and decide whether to */ - /* "echo" the key (as normal) or suppress it (as with an */ - /* arrow key). */ - keyseq buffer[80] ; - - /* Buffer "pointer" */ - int bufpnt = 0; - - - /* Test for existence of history file. */ - int exists; - exists = fexists(".history"); - printf("Result: %d \n", exists); - - while(1) - { - - int key = getch(); - - /* Printable chars. */ - if ( (key >= 32) && (key <= 126) ) - { - buffer[bufpnt].key = key; - bufpnt += 1; - } - - /* Up arrow is 27, 91, 65. ( ESC [ A ) */ - /* Down arrow is 27, 91, 66. ( ESC [ B ) */ - /* Right arrow is 27, 91, 67. ( ESC [ C ) */ - /* Left arrow is 27, 91, 68. ( ESC [ D ) */ - /* Function keys. */ - /* F2 is 27, 79, 81. */ - /* F3 is 27, 79, 82. */ - /* F4 is 27, 79, 83. */ - - - else if(key == 27) - { - - buffer[bufpnt].esc = 1; - bufpnt += 1; - key = getch(); - if(key == 91) - buffer[bufpnt].lbr = 1; - bufpnt += 1; - key = getch(); - if( (key >= 65) && (key <= 68) ) - { - buffer[bufpnt].key = key; - bufpnt += 1; - } - } - - - - /* The Enter key exits. Enter is 10 decimal */ - else if(key == 10) - { - int j ; - /* Print the array of structs. */ - for (j=0; j<20; j++) - { - printf("Fnkey: %d ", buffer[j].fnkey ) ; - printf("Ctrl: %d ", buffer[j].ctrl ) ; - printf("Alt: %d ", buffer[j].alt ) ; - printf("Shf: %d ", buffer[j].shf ) ; - printf("Esc: %d ", buffer[j].esc ) ; - printf("Lbr: %d ", buffer[j].lbr ) ; - printf("Key: %d \n", buffer[j].key ) ; - } - - break; - } /* Key = Enter */ - } - - return 0; -} - - - - diff --git a/pdmenu5.c b/pdmenu5.c deleted file mode 100644 index 9c8721f..0000000 --- a/pdmenu5.c +++ /dev/null @@ -1,139 +0,0 @@ - - -/* pd_readline.c */ -/* Status (as at 26th Aug 2012) : useful progress. */ -/* Keystroke sequences (along with the special flags */ -/* like Esc, Ctrl, Alt etc are now stored in a buffer */ -/* ( an array of structs ). */ -/* It will still be some time before this is a REAL */ -/* readline, but we are "on the way"...... */ -/* This code is released to the public domain. */ -/* "Share and enjoy...." ;) */ - - -#include -#include - - -/* Helper function, to let us see if a .history file */ -/* exists in the current directory. */ -int fexists(char *fname) -{ - - FILE *fptr ; - - fptr = fopen(fname, "r") ; - - if ( !fptr ) return -1 ; /* File does not exist in dir. */ - - fclose(fptr); - return 0; /* File DOES exist in dir. */ - -} - - - /* Struct to store key sequences */ -typedef struct { - int fnkey; - int ctrl; - int alt ; - int shf ; - int esc ; - int lbr ; /* For left-bracket ([) of escape sequences */ - int key; - } keyseq ; - - - - - -int main(void) -{ - - printf("Public Domain Readline \n"); - printf("NOTE! - at the moment, we are using \n"); - printf("NON-echoing reads, storing the keystrokes \n"); - printf("in a buffer \n"); - - - /* Buffer - an array of keyseq structs. */ - /* Note - now that we store the keystrokes in here, */ - /* we can look at the various flags and decide whether to */ - /* "echo" the key (as normal) or suppress it (as with an */ - /* arrow key). */ - keyseq buffer[80] ; - - /* Buffer "pointer" */ - int bufpnt = 0; - - - /* Test for existence of history file. */ - int exists; - exists = fexists(".history"); - printf("Result: %d \n", exists); - - while(1) - { - - int key = getchar(); - - /* Printable chars. */ - if ( (key >= 32) && (key <= 126) ) - { - putchar(key); - buffer[bufpnt].key = key; - bufpnt += 1; - } - - /* Up arrow is 27, 91, 65. ( ESC [ A ) */ - /* Down arrow is 27, 91, 66. ( ESC [ B ) */ - /* Right arrow is 27, 91, 67. ( ESC [ C ) */ - /* Left arrow is 27, 91, 68. ( ESC [ D ) */ - /* Function keys. */ - /* F2 is 27, 79, 81. */ - /* F3 is 27, 79, 82. */ - /* F4 is 27, 79, 83. */ - - - else if(key == 27) - { - buffer[bufpnt].esc = 1; - key = getchar(); - if(key == 91) - buffer[bufpnt].lbr = 1; - key = getchar(); - if( (key >= 65) && (key <= 68) ) - { - buffer[bufpnt].key = key; - } - bufpnt += 1; - } - - - - /* The Enter key exits. Enter is 10 decimal */ - else if(key == 10) - { - int j ; - /* Print the array of structs. */ - for (j=0; j<10; j++) - { - printf("Fnkey: %d ", buffer[j].fnkey ) ; - printf("Ctrl: %d ", buffer[j].ctrl ) ; - printf("Alt: %d ", buffer[j].alt ) ; - printf("Shf: %d ", buffer[j].shf ) ; - printf("Esc: %d ", buffer[j].esc ) ; - printf("Lbr: %d ", buffer[j].lbr ) ; - printf("Key: %d \n", buffer[j].key ) ; - } - - break; - } /* Key = Enter */ - } - - return 0; -} - - - - diff --git a/pdmenu6.c b/pdmenu6.c deleted file mode 100644 index 08e6bc3..0000000 --- a/pdmenu6.c +++ /dev/null @@ -1,154 +0,0 @@ - - -/* pd_readline.c */ -/* Status (as at 26th Aug 2012) : useful progress. */ -/* Keystroke sequences (along with the special flags */ -/* like Esc, Ctrl, Alt etc are now stored in a buffer */ -/* ( an array of structs ). */ -/* It will still be some time before this is a REAL */ -/* readline, but we are "on the way"...... */ -/* This code is released to the public domain. */ -/* "Share and enjoy...." ;) */ - - -#include -#include - - -/* Helper function, to let us see if a .history file */ -/* exists in the current directory. */ -int fexists(char *fname) -{ - - FILE *fptr ; - - fptr = fopen(fname, "r") ; - - if ( !fptr ) return -1 ; /* File does not exist in dir. */ - - fclose(fptr); - return 0; /* File DOES exist in dir. */ - -} - - - /* Struct to store key sequences */ -typedef struct { - int fnkey; - int ctrl; - int alt ; - int shf ; - int esc ; - int lbr ; /* For left-bracket ([) of escape sequences */ - int key; - } keyseq ; - - -/* A custom getchar to test the character type. */ -int mygetchar(void) -{ - int ch = getchar(); - if ( (ch >= 32) && (ch <= 126) ) - { - putchar(ch); - return ch; - } - else - { - return ch; - } - -} - - - -int main(void) -{ - - printf("Public Domain Readline \n"); - printf("NOTE! - at the moment, we are using \n"); - printf("NON-echoing reads, storing the keystrokes \n"); - printf("in a buffer \n"); - - - /* Buffer - an array of keyseq structs. */ - /* Note - now that we store the keystrokes in here, */ - /* we can look at the various flags and decide whether to */ - /* "echo" the key (as normal) or suppress it (as with an */ - /* arrow key). */ - keyseq buffer[80] ; - - /* Buffer "pointer" */ - int bufpnt = 0; - - - /* Test for existence of history file. */ - int exists; - exists = fexists(".history"); - printf("Result: %d \n", exists); - - while(1) - { - - int key = mygetchar(); - - /* Printable chars. */ - if ( (key >= 32) && (key <= 126) ) - { - putchar(key); - buffer[bufpnt].key = key; - bufpnt += 1; - } - - /* Up arrow is 27, 91, 65. ( ESC [ A ) */ - /* Down arrow is 27, 91, 66. ( ESC [ B ) */ - /* Right arrow is 27, 91, 67. ( ESC [ C ) */ - /* Left arrow is 27, 91, 68. ( ESC [ D ) */ - /* Function keys. */ - /* F2 is 27, 79, 81. */ - /* F3 is 27, 79, 82. */ - /* F4 is 27, 79, 83. */ - - - else if(key == 27) - { - buffer[bufpnt].esc = 1; - key = mygetchar(); - if(key == 91) - buffer[bufpnt].lbr = 1; - key = mygetchar(); - if( (key >= 65) && (key <= 68) ) - { - buffer[bufpnt].key = key; - } - bufpnt += 1; - } - - - - /* The Enter key exits. Enter is 10 decimal */ - else if(key == 10) - { - int j ; - /* Print the array of structs. */ - for (j=0; j<10; j++) - { - printf("Fnkey: %d ", buffer[j].fnkey ) ; - printf("Ctrl: %d ", buffer[j].ctrl ) ; - printf("Alt: %d ", buffer[j].alt ) ; - printf("Shf: %d ", buffer[j].shf ) ; - printf("Esc: %d ", buffer[j].esc ) ; - printf("Lbr: %d ", buffer[j].lbr ) ; - printf("Key: %d \n", buffer[j].key ) ; - } - - break; - } /* Key = Enter */ - } - - return 0; -} - - - - diff --git a/pdmenu7.c b/pdmenu7.c deleted file mode 100644 index 02b943d..0000000 --- a/pdmenu7.c +++ /dev/null @@ -1,186 +0,0 @@ - - -/* pd_readline2.c */ -/* Status (as at 26th Aug 2012) : useful progress. */ -/* Keystroke sequences (along with the special flags */ -/* like Esc, Ctrl, Alt etc are now stored in a buffer */ -/* ( an array of structs ). */ - -/* The code can now distinguish between a printable key */ -/* and a key that should not be printed. */ - -/* It will still be some time before this is a REAL */ -/* readline, but we are "on the way"...... */ -/* This code is released to the public domain. */ -/* "Share and enjoy...." ;) */ - - -#include -#include -#include /* For getch() */ - -/* This implementation of getch() is from here - */ -/* http://wesley.vidiqatch.org/ */ -/* Thanks, Wesley! */ -static struct termios old, new; - -/* Initialize new terminal i/o settings */ -void initTermios(int echo) { - tcgetattr(0, &old); /* grab old terminal i/o settings */ - new = old; /* make new settings same as old settings */ - new.c_lflag &= ~ICANON; /* disable buffered i/o */ - new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ - tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ -} - - -/* Restore old terminal i/o settings */ -void resetTermios(void) { - tcsetattr(0, TCSANOW, &old); -} - - -/* Read 1 character - echo defines echo mode */ -char getch_(int echo) { - char ch; - initTermios(echo); - ch = getchar(); - resetTermios(); - return ch; -} - - -/* Read 1 character without echo */ -char getch(void) { - return getch_(0); -} - - -/* Read 1 character with echo */ -char getche(void) { - return getch_(1); -} - - - -/* Helper function, to let us see if a .history file */ -/* exists in the current directory. */ -int fexists(char *fname) -{ - - FILE *fptr ; - - fptr = fopen(fname, "r") ; - - if ( !fptr ) return -1 ; /* File does not exist in dir. */ - - fclose(fptr); - return 0; /* File DOES exist in dir. */ - -} - - - /* Struct to store key sequences */ -typedef struct { - int fnkey; - int ctrl; - int alt ; - int shf ; - int esc ; - int lbr ; /* For left-bracket ([) of escape sequences */ - int key; - } keyseq ; - - - - - -int main(void) -{ - - printf("Public Domain Readline \n"); - - /* Buffer - an array of keyseq structs. */ - /* Note - now that we store the keystrokes in here, */ - /* we can look at the various flags and decide whether to */ - /* "echo" the key (as normal) or suppress it (as with an */ - /* arrow key). */ - keyseq buffer[80] ; - - /* Buffer "pointer" */ - int bufpnt = 0; - - - /* Test for existence of history file. */ - int exists; - exists = fexists(".history"); - printf("Result: %d \n", exists); - - while(1) - { - - int key = getch(); - - /* Printable chars. */ - if ( (key >= 32) && (key <= 126) ) - { - /* We have a printable key so print it. */ - putchar(key); - buffer[bufpnt].key = key; - bufpnt += 1; - } - - /* Up arrow is 27, 91, 65. ( ESC [ A ) */ - /* Down arrow is 27, 91, 66. ( ESC [ B ) */ - /* Right arrow is 27, 91, 67. ( ESC [ C ) */ - /* Left arrow is 27, 91, 68. ( ESC [ D ) */ - /* Function keys. */ - /* F2 is 27, 79, 81. */ - /* F3 is 27, 79, 82. */ - /* F4 is 27, 79, 83. */ - - - else if(key == 27) - { - - buffer[bufpnt].esc = 1; - key = getch(); - if(key == 91) - buffer[bufpnt].lbr = 1; - key = getch(); - if( (key >= 65) && (key <= 68) ) - { - buffer[bufpnt].key = key; - } - bufpnt += 1; - } - - - - /* The Enter key exits. Enter is 10 decimal */ - else if(key == 10) - { - puts("\n"); - int j ; - /* Print the array of structs. */ - for (j=0; j<20; j++) - { - printf("Fnkey: %d ", buffer[j].fnkey ) ; - printf("Ctrl: %d ", buffer[j].ctrl ) ; - printf("Alt: %d ", buffer[j].alt ) ; - printf("Shf: %d ", buffer[j].shf ) ; - printf("Esc: %d ", buffer[j].esc ) ; - printf("Lbr: %d ", buffer[j].lbr ) ; - printf("Key: %d \n", buffer[j].key ) ; - } - - break; - } /* Key = Enter */ - } - - return 0; -} - - - - diff --git a/pdmenu8.c b/pdmenu8.c deleted file mode 100644 index 63a31e7..0000000 --- a/pdmenu8.c +++ /dev/null @@ -1,212 +0,0 @@ - - -/* pd_readline2.c */ -/* Status (as at 26th Aug 2012) : useful progress. */ -/* Keystroke sequences (along with the special flags */ -/* like Esc, Ctrl, Alt etc are now stored in a buffer */ -/* ( an array of structs ). */ - -/* The code can now distinguish between a printable key */ -/* and a key that should not be printed. */ - -/* Backspace key, and left and right arrow keys now work. */ - -/* It will still be some time before this is a REAL */ -/* readline, but we are "on the way"...... */ -/* This code is released to the public domain. */ -/* "Share and enjoy...." ;) */ - - -#include -#include -#include /* For getch() */ - -/* This implementation of getch() is from here - */ -/* http://wesley.vidiqatch.org/ */ -/* Thanks, Wesley! */ -static struct termios old, new; - -/* Initialize new terminal i/o settings */ -void initTermios(int echo) { - tcgetattr(0, &old); /* grab old terminal i/o settings */ - new = old; /* make new settings same as old settings */ - new.c_lflag &= ~ICANON; /* disable buffered i/o */ - new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ - tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ -} - - -/* Restore old terminal i/o settings */ -void resetTermios(void) { - tcsetattr(0, TCSANOW, &old); -} - - -/* Read 1 character - echo defines echo mode */ -char getch_(int echo) { - char ch; - initTermios(echo); - ch = getchar(); - resetTermios(); - return ch; -} - - -/* Read 1 character without echo */ -char getch(void) { - return getch_(0); -} - - -/* Read 1 character with echo */ -char getche(void) { - return getch_(1); -} - - - -/* Helper function, to let us see if a .history file */ -/* exists in the current directory. */ -int fexists(char *fname) -{ - - FILE *fptr ; - - fptr = fopen(fname, "r") ; - - if ( !fptr ) return -1 ; /* File does not exist in dir. */ - - fclose(fptr); - return 0; /* File DOES exist in dir. */ - -} - - - /* Struct to store key sequences */ -typedef struct { - int fnkey; - int ctrl; - int alt ; - int shf ; - int esc ; - int lbr ; /* For left-bracket ([) of escape sequences */ - int key; - } keyseq ; - - - - - -int main(void) -{ - - printf("Public Domain Readline \n"); - - /* Buffer - an array of keyseq structs. */ - /* Note - now that we store the keystrokes in here, */ - /* we can look at the various flags and decide whether to */ - /* "echo" the key (as normal) or suppress it (as with an */ - /* arrow key). */ - keyseq buffer[80] ; - - /* Buffer "pointer" */ - int bufpnt = 0; - - - /* Test for existence of history file. */ - int exists; - exists = fexists(".history"); - printf("Result: %d \n", exists); - - while(1) - { - - int key = getch(); - - /* Printable chars. */ - if ( (key >= 32) && (key <= 126) ) - { - /* We have a printable key so print it. */ - putchar(key); - buffer[bufpnt].key = key; - bufpnt += 1; - } - - /* Up arrow is 27, 91, 65. ( ESC [ A ) */ - /* Down arrow is 27, 91, 66. ( ESC [ B ) */ - /* Right arrow is 27, 91, 67. ( ESC [ C ) */ - /* Left arrow is 27, 91, 68. ( ESC [ D ) */ - /* Function keys. */ - /* F2 is 27, 79, 81. */ - /* F3 is 27, 79, 82. */ - /* F4 is 27, 79, 83. */ - - /* Backspace */ - else if(key == 127) - { - buffer[bufpnt].key = key; - /* Move 1 char to left */ - printf("\033[1D"); - printf("\040"); - printf("\033[1D"); - bufpnt += 1; - } - - else if(key == 27) - { - buffer[bufpnt].esc = 1; - key = getch(); - if(key == 91) - buffer[bufpnt].lbr = 1; - key = getch(); - if(key == 65) /* Up arrow */ - { - buffer[bufpnt].key = key; - } - if(key == 66) /* Down arrow */ - { - buffer[bufpnt].key = key; - } - if(key == 67) /* Left arrow */ - { - buffer[bufpnt].key = key; - printf("\033[1C"); - } - if(key == 68) /* Right arrow */ - { - buffer[bufpnt].key = key; - printf("\033[1D"); - } - - bufpnt += 1; - } - - - - /* The Enter key exits. Enter is 10 decimal */ - else if(key == 10) - { - puts("\n"); - int j ; - /* Print the array of structs. */ - for (j=0; j -#include -#include /* For getch() */ - -/* This implementation of getch() is from here - */ -/* http://wesley.vidiqatch.org/ */ -/* Thanks, Wesley! */ -static struct termios old, new; - -/* Initialize new terminal i/o settings */ -void initTermios(int echo) { - tcgetattr(0, &old); /* grab old terminal i/o settings */ - new = old; /* make new settings same as old settings */ - new.c_lflag &= ~ICANON; /* disable buffered i/o */ - new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ - tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ -} - - -/* Restore old terminal i/o settings */ -void resetTermios(void) { - tcsetattr(0, TCSANOW, &old); -} - - -/* Read 1 character - echo defines echo mode */ -char getch_(int echo) { - char ch; - initTermios(echo); - ch = getchar(); - resetTermios(); - return ch; -} - - -/* Read 1 character without echo */ -char getch(void) { - return getch_(0); -} - - -/* Read 1 character with echo */ -char getche(void) { - return getch_(1); -} - - - -/* Helper function, to let us see if a .history file */ -/* exists in the current directory. */ -int fexists(char *fname) -{ - - FILE *fptr ; - - fptr = fopen(fname, "r") ; - - if ( !fptr ) return -1 ; /* File does not exist in dir. */ - - fclose(fptr); - return 0; /* File DOES exist in dir. */ - -} - - -/* Helper function to print escape sequences to terminal */ -void prtseq(char *what) -{ - if (strcmp(what, "left") ) printf("\033[1D"); - else if (strcmp(what, "right") ) printf("\033[1C"); - else if (strcmp(what, "bs") ) - printf("\033[1D"); - printf("\040"); - printf("\033[1D"); -} - - - - - /* Struct to store key sequences */ -typedef struct { - int fnkey; - int ctrl; - int alt ; - int shf ; - int esc ; - int lbr ; /* For left-bracket ([) of escape sequences */ - int key; - } keyseq ; - - - - - -int main(void) -{ - - printf("Public Domain Readline \n"); - - /* Buffer - an array of keyseq structs. */ - /* Note - now that we store the keystrokes in here, */ - /* we can look at the various flags and decide whether to */ - /* "echo" the key (as normal) or suppress it (as with an */ - /* arrow key). */ - keyseq buffer[80] ; - - /* Buffer "pointer" */ - int bufpnt = 0; - - - /* Test for existence of history file. */ - int exists; - exists = fexists(".history"); - printf("Result: %d \n", exists); - - while(1) - { - - int key = getch(); - - /* Printable chars. */ - if ( (key >= 32) && (key <= 126) ) - { - /* We have a printable key so print it. */ - putchar(key); - buffer[bufpnt].key = key; - bufpnt += 1; - } - - /* Up arrow is 27, 91, 65. ( ESC [ A ) */ - /* Down arrow is 27, 91, 66. ( ESC [ B ) */ - /* Right arrow is 27, 91, 67. ( ESC [ C ) */ - /* Left arrow is 27, 91, 68. ( ESC [ D ) */ - /* Function keys. */ - /* F2 is 27, 79, 81. */ - /* F3 is 27, 79, 82. */ - /* F4 is 27, 79, 83. */ - - /* Backspace */ - else if(key == 127) - { - buffer[bufpnt].key = key; - /* Move 1 char to left */ - prtseq("bs"); - bufpnt += 1; - } - - else if(key == 27) - { - buffer[bufpnt].esc = 1; - key = getch(); - if(key == 91) - buffer[bufpnt].lbr = 1; - key = getch(); - if(key == 65) /* Up arrow */ - { - buffer[bufpnt].key = key; - } - if(key == 66) /* Down arrow */ - { - buffer[bufpnt].key = key; - } - if(key == 67) /* Left arrow */ - { - buffer[bufpnt].key = key; - prtseq("left"); - } - if(key == 68) /* Right arrow */ - { - buffer[bufpnt].key = key; - prtseq("right"); - } - - bufpnt += 1; - } - - - - /* The Enter key exits. Enter is 10 decimal */ - else if(key == 10) - { - puts("\n"); - int j ; - /* Print the array of structs. */ - for (j=0; j +#include + + + +/* Helper function, to let us see if a file */ +/* exists in the current directory. */ +int fexists(char *fname) +{ + FILE *fptr; + fptr = fopen(fname, "r") ; + if ( !fptr ) return -1 ; /* File does not exist in dir. */ + fclose(fptr); + return 0; /* File DOES exist in dir. */ +} + + +/* Helper function to chop newlines off the lines read in. */ +/* Without this being done, an extra newline is inserted */ +/* (which is usually not what is wanted). */ +void chop(char *s) +{ + s[strcspn(s,"\n")] = '\0'; +} + + +/* An array to store the file in. */ +/* Only 20 lines are read. */ +char myarray[20][80]; + + +/* Read the file into the array of strings. */ +void readfile(char *fname) +{ + int retval = fexists(fname); + + int i; + if (retval == 0) { + /* File exists, so open it. */ + /* We open it in read-write mode so we can */ + /* append new commands to it. */ + FILE *fptr; + fptr = fopen(fname, "rw"); + + for(i=0; i<20; i++) + { + chop(fgets(myarray[i], 80, fptr) ); + } + + } /* retval == 0 */ + + else puts("Error! File does not exist. \n"); + +} + + +void printfile(void) +{ + int j; + + for(j=0; j<10; j++) + { + puts(myarray[j]); + } + +} + + + +int main(void) +{ + +readfile("test.txt"); + +printfile(); + + +return 0; + +} + + + + + + + + + diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..a462081 --- /dev/null +++ b/test.txt @@ -0,0 +1,21 @@ +This is just a text file to use when playing around with reading and writing. +sdgvkslzdnglsjndgk +sdkgskdnglksdjng +slDKGN;sdgnl;ksd +*** Line 5 *** +kladsjnglksadjng +;ladsfngkfdsangldkfjnglkdfjnglkdafjg +adfgnsakdfgnlkadsfjnglksdgnslkadgnldskgjnsldkgjnlskdjgnsdkgn +aksjgnlsdkagjnlskadgjnlskadjnglkdsjgnlksdjgn +*** Line 10 *** +dsglknsldkgjnlkdfgjnlksdjfnglkdsjfnglkjdfsnglksjdfnglkjsdfnglkdjfsng +dfkjgnldkfjnglksdfjnglkdsfjnglkdsjfngkdjsfnglkjdsfng +dfgndlksgnldkfsjngldskfjnglkdfsjnglkdfjnglkdfjngkdfsjngldkfjgn +dfkngldfjngldksjfnglkdfjsnglkdsjfnglkjdsngjdfngljdsg +*** Line 15 *** +ldfnvgkljdfsnglkdjfglkjfdglkjndskgjdfljgnldksfjngkldsfjngkldjng +dlfkmsdfmg;ldskfmg;lsdfkmg;lsdfkmg;ldfkmg;lkdsmfg +dfkgmdsfkgm;lsdfkmg;lsdfkmgl;dsfmg;ldskfmg +lkmsd;glsadgnsdlkgnjslkadjgnlskdajnglksajdgnlskdajngk +*** Line 20 *** + diff --git a/testkey.c b/testkey.c deleted file mode 100644 index f6e6246..0000000 --- a/testkey.c +++ /dev/null @@ -1,26 +0,0 @@ - - -/* testkey.c */ - -/* Prints the keycode for a given key */ - - - -#include -#include - - - -int main (void) -{ - -int c; - -while( (c == getchar() ) ) -{ - printf("%d 0x%02X\n", c ); -} - -return 0; - -}