From 4bb27266f935c9aafad6870ffc8847fc65c8120f Mon Sep 17 00:00:00 2001 From: andy Date: Wed, 5 Sep 2012 20:13:59 +1200 Subject: [PATCH] Getting close to a basic working readline now. --- .history | 17 - Notes_and_ideas.txt | 13 - README | 31 +- keyhandler.c | 165 ------- mg/Makefile | 34 -- mg/autoexec.c | 111 ----- mg/basic.c | 532 ---------------------- mg/buffer.c | 863 ----------------------------------- mg/chrdef.h | 81 ---- mg/cinfo.c | 154 ------- mg/cmode.c | 528 --------------------- mg/cscope.c | 609 ------------------------- mg/def.h | 707 ---------------------------- mg/dir.c | 77 ---- mg/dired.c | 779 ------------------------------- mg/display.c | 1064 ------------------------------------------- mg/echo.c | 964 --------------------------------------- mg/extend.c | 963 --------------------------------------- mg/file.c | 715 ----------------------------- mg/fileio.c | 754 ------------------------------ mg/funmap.c | 281 ------------ mg/funmap.h | 9 - mg/grep.c | 365 --------------- mg/help.c | 231 ---------- mg/kbd.c | 436 ------------------ mg/kbd.h | 58 --- mg/key.h | 14 - mg/keymap.c | 567 ----------------------- mg/line.c | 635 -------------------------- mg/macro.c | 106 ----- mg/macro.h | 21 - mg/main.c | 245 ---------- mg/match.c | 185 -------- mg/mg.1 | 956 -------------------------------------- mg/modes.c | 165 ------- mg/paragraph.c | 362 --------------- mg/pathnames.h | 11 - mg/random.c | 496 -------------------- mg/re_search.c | 615 ------------------------- mg/region.c | 597 ------------------------ mg/spawn.c | 48 -- mg/sysdef.h | 30 -- mg/tags.c | 533 ---------------------- mg/theo.c | 192 -------- mg/tty.c | 447 ------------------ mg/ttydef.h | 25 - mg/ttyio.c | 225 --------- mg/ttykbd.c | 89 ---- mg/tutorial | 349 -------------- mg/undo.c | 585 ------------------------ mg/version.c | 24 - mg/window.c | 428 ----------------- mg/word.c | 346 -------------- mg/yank.c | 264 ----------- pd_readline.c | 442 ++++++++++-------- pd_readline2.c | 212 --------- pdmenu.c | 130 ------ pdmenu2.c | 170 ------- pdmenu3.c | 186 -------- pdmenu4.c | 185 -------- pdmenu5.c | 139 ------ pdmenu6.c | 154 ------- pdmenu7.c | 186 -------- pdmenu8.c | 212 --------- pdmenu9.c | 224 --------- readfile.c | 98 ++++ test.txt | 21 + testkey.c | 26 -- 68 files changed, 393 insertions(+), 21093 deletions(-) delete mode 100644 .history delete mode 100644 Notes_and_ideas.txt delete mode 100644 keyhandler.c delete mode 100644 mg/Makefile delete mode 100644 mg/autoexec.c delete mode 100644 mg/basic.c delete mode 100644 mg/buffer.c delete mode 100644 mg/chrdef.h delete mode 100644 mg/cinfo.c delete mode 100644 mg/cmode.c delete mode 100644 mg/cscope.c delete mode 100644 mg/def.h delete mode 100644 mg/dir.c delete mode 100644 mg/dired.c delete mode 100644 mg/display.c delete mode 100644 mg/echo.c delete mode 100644 mg/extend.c delete mode 100644 mg/file.c delete mode 100644 mg/fileio.c delete mode 100644 mg/funmap.c delete mode 100644 mg/funmap.h delete mode 100644 mg/grep.c delete mode 100644 mg/help.c delete mode 100644 mg/kbd.c delete mode 100644 mg/kbd.h delete mode 100644 mg/key.h delete mode 100644 mg/keymap.c delete mode 100644 mg/line.c delete mode 100644 mg/macro.c delete mode 100644 mg/macro.h delete mode 100644 mg/main.c delete mode 100644 mg/match.c delete mode 100644 mg/mg.1 delete mode 100644 mg/modes.c delete mode 100644 mg/paragraph.c delete mode 100644 mg/pathnames.h delete mode 100644 mg/random.c delete mode 100644 mg/re_search.c delete mode 100644 mg/region.c delete mode 100644 mg/spawn.c delete mode 100644 mg/sysdef.h delete mode 100644 mg/tags.c delete mode 100644 mg/theo.c delete mode 100644 mg/tty.c delete mode 100644 mg/ttydef.h delete mode 100644 mg/ttyio.c delete mode 100644 mg/ttykbd.c delete mode 100644 mg/tutorial delete mode 100644 mg/undo.c delete mode 100644 mg/version.c delete mode 100644 mg/window.c delete mode 100644 mg/word.c delete mode 100644 mg/yank.c delete mode 100644 pd_readline2.c delete mode 100644 pdmenu.c delete mode 100644 pdmenu2.c delete mode 100644 pdmenu3.c delete mode 100644 pdmenu4.c delete mode 100644 pdmenu5.c delete mode 100644 pdmenu6.c delete mode 100644 pdmenu7.c delete mode 100644 pdmenu8.c delete mode 100644 pdmenu9.c create mode 100644 readfile.c create mode 100644 test.txt delete mode 100644 testkey.c 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; - -} -- 2.40.0