+++ /dev/null
-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
-
+++ /dev/null
-
- **** 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.
-
-
***** 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
+++ /dev/null
-
-
-/* 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <ctype.h>
-
-
-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;
-
-}
-
-
-
+++ /dev/null
-# $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
-
-
+++ /dev/null
-/* $OpenBSD: autoexec.c,v 1.14 2007/02/08 21:40:03 kjell Exp $ */
-/* this file is in the public domain */
-/* Author: Vincent Labrecque <vincent@openbsd.org> April 2002 */
-
-#include "def.h"
-#include "funmap.h"
-
-#include <fnmatch.h>
-
-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 <fname>. 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);
-}
+++ /dev/null
-/* $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 <ctype.h>
-
-/*
- * 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);
-}
+++ /dev/null
-/* $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 <libgen.h>
-#include <stdarg.h>
-
-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);
-}
-
+++ /dev/null
-/* $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
+++ /dev/null
-/* $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);
-}
+++ /dev/null
-/* $OpenBSD: cmode.c,v 1.8 2012/05/18 02:13:44 lum Exp $ */
-/*
- * This file is in the public domain.
- *
- * Author: Kjell Wooding <kjell@openbsd.org>
- */
-
-/*
- * Implement an non-irritating KNF-compliant mode for editing
- * C code.
- */
-#include <ctype.h>
-
-#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);
-}
+++ /dev/null
-/* $OpenBSD: cscope.c,v 1.3 2012/07/02 08:08:31 lum Exp $ */
-
-/*
- * This file is in the public domain.
- *
- * Author: Sunil Nimmagadda <sunil@sunilnimmagadda.com>
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/queue.h>
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <fnmatch.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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: <filename> <function> <lineno> <pattern>
- */
-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);
-}
+++ /dev/null
-/* $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 */
+++ /dev/null
-/* $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);
-}
+++ /dev/null
-/* $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 <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/wait.h>
-
-#include <ctype.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <libgen.h>
-#include <stdarg.h>
-
-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);
-}
+++ /dev/null
-/* $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 <ctype.h>
-
-/*
- * 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 <term.h>
-#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]);
-}
+++ /dev/null
-/* $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 <stdarg.h>
-#include <term.h>
-
-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);
-}
+++ /dev/null
-/* $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 <sys/types.h>
-#include <ctype.h>
-
-#include "macro.h"
-
-#ifdef FKEYS
-#include "key.h"
-#ifndef BINDKEY
-#define BINDKEY /* bindkey is used by FKEYS startup code */
-#endif /* !BINDKEY */
-#endif /* FKEYS */
-
-#include <ctype.h>
-
-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);
-}
+++ /dev/null
-/* $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 <sys/stat.h>
-
-#include <libgen.h>
-
-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));
-}
+++ /dev/null
-/* $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 <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/wait.h>
-
-#include <fcntl.h>
-#include <limits.h>
-#include <dirent.h>
-#include <pwd.h>
-#include <string.h>
-#include <unistd.h>
-
-#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);
-}
+++ /dev/null
-/* $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);
-}
+++ /dev/null
-/* $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 *);
+++ /dev/null
-/* $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 <sys/types.h>
-#include <ctype.h>
-#include <libgen.h>
-#include <time.h>
-
-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);
-}
+++ /dev/null
-/* $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);
-}
+++ /dev/null
-/* $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));
-}
+++ /dev/null
-/* $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[];
+++ /dev/null
-/* $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;
+++ /dev/null
-/* $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);
-}
+++ /dev/null
-/* $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 <stdlib.h>
-#include <string.h>
-
-/*
- * 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);
-}
+++ /dev/null
-/* $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);
-}
+++ /dev/null
-/* $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;
+++ /dev/null
-/* $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 <err.h>
-
-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);
-}
+++ /dev/null
-/* $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);
- }
-}
+++ /dev/null
-.\" $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-<n> (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 <NL><NL> or <NL><TAB> or <NL><SPACE>.
-.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 <NL><NL> or <NL><TAB> or <NL><SPACE>.
-.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.
-
+++ /dev/null
-/* $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);
-}
+++ /dev/null
-/* $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 <NL><NL> or <NL><TAB> or <NL><SPACE>
- * 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 <NL><SP> <NL><TAB> or
- * <NL><NL>
- */
- 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 <NL><NL> or <NL><TAB> or <NL><SPACE> 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 <NL><SP> 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);
-}
+++ /dev/null
-/* $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"
+++ /dev/null
-/* $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 <ctype.h>
-
-/*
- * 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);
-}
+++ /dev/null
-/* $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 <sys/types.h>
-#include <regex.h>
-
-#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("<SP> replace, [.] rep-end, <DEL> don't, [!] repl rest <ESC> quit");
- goto retry;
- }
- }
-
-stopsearch:
- curwp->w_rflag |= WFFULL;
- update();
- if (!inmacro) {
- if (rcnt == 0)
- ewprintf("(No replacements done)");
- else if (rcnt == 1)
- ewprintf("(1 replacement done)");
- else
- ewprintf("(%d replacements done)", rcnt);
- }
- return (TRUE);
-}
-
-/*
- * 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 */
+++ /dev/null
-/* $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 <sys/types.h>
-#include <sys/socket.h>
-
-#include <fcntl.h>
-#include <poll.h>
-#include <string.h>
-#include <unistd.h>
-
-#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);
-}
+++ /dev/null
-/* $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 <termios.h>
-#include <term.h>
-
-/*
- * 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());
-}
+++ /dev/null
-/* $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 <sys/param.h>
-#include <sys/queue.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <signal.h>
-
-#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 */
-};
+++ /dev/null
-/* $OpenBSD: tags.c,v 1.5 2012/07/02 08:08:31 lum Exp $ */
-
-/*
- * This file is in the public domain.
- *
- * Author: Sunil Nimmagadda <sunil@sunilnimmagadda.com>
- */
-
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/tree.h>
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <stdlib.h>
-#include <string.h>
-#include <util.h>
-
-#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 "<tag>\t<filename>\t<pattern>". 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);
-}
+++ /dev/null
-/* $OpenBSD: theo.c,v 1.124 2012/07/09 22:24:36 mlarkin Exp $ */
-/*
- * Copyright (c) 2002 Artur Grabowski <art@openbsd.org>
- * 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);
-}
+++ /dev/null
-/* $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 <sys/types.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-
-#include <term.h>
-
-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);
-}
+++ /dev/null
-/* $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 */
+++ /dev/null
-/* $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 <sys/types.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <term.h>
-
-#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);
-}
+++ /dev/null
-/* $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 <term.h>
-
-#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 */
+++ /dev/null
-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-<chr> means hold down the Control key while typing the character <chr>.
- M-<chr> means hold down the Meta key while typing the character <chr>.
-
-If you don't have a Meta key, you can use Esc instead. Press and release the
-Esc key and type <chr>. This is equivalent to M-<chr>.
-
-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-<chr> will perform one function and M-<chr>
-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-<backspace> (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-<space> 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.
-
-
+++ /dev/null
-/* $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);
-}
+++ /dev/null
-/* $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);
-}
+++ /dev/null
-/* $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);
-}
+++ /dev/null
-/* $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]));
-}
+++ /dev/null
-/* $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 <string.h>
-
-#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);
-}
-
-\r
-\r
-/* pd_readline.c */ \r
-/* Status (as at 26th Aug 2012) : useful progress. */ \r
-/* Keystroke sequences (along with the special flags */ \r
-/* like Esc, Ctrl, Alt etc are now stored in a buffer */ \r
-/* ( an array of structs ). */ \r
-/* It will still be some time before this is a REAL */ \r
-/* readline, but we are "on the way"...... */ \r
-/* This code is released to the public domain. */ \r
-/* "Share and enjoy...." ;) */ \r
-\r
-\r
-#include <string.h> \r
-#include <stdio.h> \r
-#include <termios.h> /* For getch() */ \r
-\r
-/* This implementation of getch() is from here - */ \r
-/* http://wesley.vidiqatch.org/ */ \r
-/* Thanks, Wesley! */ \r
-static struct termios old, new;\r
-\r
-/* Initialize new terminal i/o settings */\r
-void initTermios(int echo) {\r
- tcgetattr(0, &old); /* grab old terminal i/o settings */\r
- new = old; /* make new settings same as old settings */\r
- new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
- new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
- tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
-}\r
-\r
-\r
-/* Restore old terminal i/o settings */\r
-void resetTermios(void) {\r
- tcsetattr(0, TCSANOW, &old);\r
-}\r
-\r
-\r
-/* Read 1 character - echo defines echo mode */\r
-char getch_(int echo) {\r
- char ch;\r
- initTermios(echo);\r
- ch = getchar();\r
- resetTermios();\r
- return ch;\r
-}\r
-\r
-\r
-/* Read 1 character without echo */\r
-char getch(void) {\r
- return getch_(0);\r
-}\r
-\r
-\r
-/* Read 1 character with echo */\r
-char getche(void) {\r
- return getch_(1);\r
-} \r
-\r
-\r
-\r
-/* Helper function, to let us see if a .history file */ \r
-/* exists in the current directory. */ \r
-int fexists(char *fname)\r
-{ \r
-\r
- FILE *fptr ; \r
- \r
- fptr = fopen(fname, "r") ; \r
- \r
- if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
- \r
- fclose(fptr); \r
- return 0; /* File DOES exist in dir. */ \r
-\r
-} \r
-\r
-\r
- /* Struct to store key sequences */ \r
-typedef struct { \r
- int fnkey; \r
- int ctrl; \r
- int alt ; \r
- int shf ; \r
- int esc ; \r
- int lbr ; /* For left-bracket ([) of escape sequences */ \r
- int key; \r
- } keyseq ; \r
-\r
-\r
-\r
-\r
-\r
-int main(void)\r
-{\r
- \r
- printf("Public Domain Readline \n"); \r
- printf("NOTE! - at the moment, we are using \n"); \r
- printf("NON-echoing reads, storing the keystrokes \n"); \r
- printf("in a buffer \n"); \r
- \r
- \r
- /* Buffer - an array of keyseq structs. */ \r
- /* Note - now that we store the keystrokes in here, */ \r
- /* we can look at the various flags and decide whether to */ \r
- /* "echo" the key (as normal) or suppress it (as with an */ \r
- /* arrow key). */ \r
- keyseq buffer[80] ; \r
- \r
- /* Buffer "pointer" */ \r
- int bufpnt = 0; \r
- \r
- \r
- /* Test for existence of history file. */ \r
- int exists; \r
- exists = fexists(".history"); \r
- printf("Result: %d \n", exists); \r
- \r
- while(1) \r
- { \r
- \r
- int key = getch(); \r
- \r
- /* Printable chars. */ \r
- if ( (key >= 32) && (key <= 126) ) \r
- { \r
- buffer[bufpnt].key = key; \r
- bufpnt += 1; \r
- } \r
- \r
- /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
- /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
- /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
- /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
- /* Function keys. */ \r
- /* F2 is 27, 79, 81. */ \r
- /* F3 is 27, 79, 82. */ \r
- /* F4 is 27, 79, 83. */ \r
- \r
- \r
- else if(key == 27) \r
- { \r
- \r
- buffer[bufpnt].esc = 1; \r
- key = getch(); \r
- if(key == 91) \r
- buffer[bufpnt].lbr = 1; \r
- key = getch(); \r
- if( (key >= 65) && (key <= 68) ) \r
- { \r
- buffer[bufpnt].key = key; \r
- } \r
- bufpnt += 1; \r
- } \r
- \r
- \r
- \r
- /* The Enter key exits. Enter is 10 decimal */ \r
- else if(key == 10) \r
- { \r
- int j ; \r
- /* Print the array of structs. */ \r
- for (j=0; j<10; j++) \r
- { \r
- printf("Fnkey: %d ", buffer[j].fnkey ) ; \r
- printf("Ctrl: %d ", buffer[j].ctrl ) ; \r
- printf("Alt: %d ", buffer[j].alt ) ; \r
- printf("Shf: %d ", buffer[j].shf ) ; \r
- printf("Esc: %d ", buffer[j].esc ) ; \r
- printf("Lbr: %d ", buffer[j].lbr ) ; \r
- printf("Key: %d \n", buffer[j].key ) ; \r
- } \r
- \r
- break; \r
- } /* Key = Enter */ \r
- } \r
- \r
- return 0;\r
-} \r
-\r
-\r
-\r
-\r
+
+
+/* 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 <string.h>
+#include <stdio.h>
+#include <termios.h>
+
+/* 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;
+
+}
+
+
+
+
+
+
+++ /dev/null
-\r
-\r
-/* pd_readline2.c */ \r
-/* Status (as at 26th Aug 2012) : useful progress. */ \r
-/* Keystroke sequences (along with the special flags */ \r
-/* like Esc, Ctrl, Alt etc are now stored in a buffer */ \r
-/* ( an array of structs ). */ \r
-\r
-/* The code can now distinguish between a printable key */ \r
-/* and a key that should not be printed. */ \r
-\r
-/* Backspace key, and left and right arrow keys now work. */ \r
-\r
-/* It will still be some time before this is a REAL */ \r
-/* readline, but we are "on the way"...... */ \r
-/* This code is released to the public domain. */ \r
-/* "Share and enjoy...." ;) */ \r
-\r
-\r
-#include <string.h> \r
-#include <stdio.h> \r
-#include <termios.h> /* For getch() */ \r
-\r
-/* This implementation of getch() is from here - */ \r
-/* http://wesley.vidiqatch.org/ */ \r
-/* Thanks, Wesley! */ \r
-static struct termios old, new;\r
-\r
-/* Initialize new terminal i/o settings */\r
-void initTermios(int echo) {\r
- tcgetattr(0, &old); /* grab old terminal i/o settings */\r
- new = old; /* make new settings same as old settings */\r
- new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
- new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
- tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
-}\r
-\r
-\r
-/* Restore old terminal i/o settings */\r
-void resetTermios(void) {\r
- tcsetattr(0, TCSANOW, &old);\r
-}\r
-\r
-\r
-/* Read 1 character - echo defines echo mode */\r
-char getch_(int echo) {\r
- char ch;\r
- initTermios(echo);\r
- ch = getchar();\r
- resetTermios();\r
- return ch;\r
-}\r
-\r
-\r
-/* Read 1 character without echo */\r
-char getch(void) {\r
- return getch_(0);\r
-}\r
-\r
-\r
-/* Read 1 character with echo */\r
-char getche(void) {\r
- return getch_(1);\r
-} \r
-\r
-\r
-\r
-/* Helper function, to let us see if a .history file */ \r
-/* exists in the current directory. */ \r
-int fexists(char *fname)\r
-{ \r
-\r
- FILE *fptr ; \r
- \r
- fptr = fopen(fname, "r") ; \r
- \r
- if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
- \r
- fclose(fptr); \r
- return 0; /* File DOES exist in dir. */ \r
-\r
-} \r
-\r
-\r
- /* Struct to store key sequences */ \r
-typedef struct { \r
- int fnkey; \r
- int ctrl; \r
- int alt ; \r
- int shf ; \r
- int esc ; \r
- int lbr ; /* For left-bracket ([) of escape sequences */ \r
- int key; \r
- } keyseq ; \r
-\r
-\r
-\r
-\r
-\r
-int main(void)\r
-{\r
- \r
- printf("Public Domain Readline \n"); \r
- \r
- /* Buffer - an array of keyseq structs. */ \r
- /* Note - now that we store the keystrokes in here, */ \r
- /* we can look at the various flags and decide whether to */ \r
- /* "echo" the key (as normal) or suppress it (as with an */ \r
- /* arrow key). */ \r
- keyseq buffer[80] ; \r
- \r
- /* Buffer "pointer" */ \r
- int bufpnt = 0; \r
- \r
- \r
- /* Test for existence of history file. */ \r
- int exists; \r
- exists = fexists(".history"); \r
- printf("Result: %d \n", exists); \r
- \r
- while(1) \r
- { \r
- \r
- int key = getch(); \r
- \r
- /* Printable chars. */ \r
- if ( (key >= 32) && (key <= 126) ) \r
- { \r
- /* We have a printable key so print it. */ \r
- putchar(key); \r
- buffer[bufpnt].key = key; \r
- bufpnt += 1; \r
- } \r
- \r
- /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
- /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
- /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
- /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
- /* Function keys. */ \r
- /* F2 is 27, 79, 81. */ \r
- /* F3 is 27, 79, 82. */ \r
- /* F4 is 27, 79, 83. */ \r
- \r
- /* Backspace */ \r
- else if(key == 127) \r
- { \r
- buffer[bufpnt].key = key; \r
- /* Move 1 char to left */ \r
- printf("\033[1D");\r
- printf("\040"); \r
- printf("\033[1D"); \r
- bufpnt += 1; \r
- } \r
- \r
- else if(key == 27) \r
- { \r
- buffer[bufpnt].esc = 1; \r
- key = getch(); \r
- if(key == 91) \r
- buffer[bufpnt].lbr = 1; \r
- key = getch(); \r
- if(key == 65) /* Up arrow */ \r
- { \r
- buffer[bufpnt].key = key; \r
- } \r
- if(key == 66) /* Down arrow */ \r
- { \r
- buffer[bufpnt].key = key; \r
- } \r
- if(key == 67) /* Left arrow */ \r
- { \r
- buffer[bufpnt].key = key; \r
- printf("\033[1C"); \r
- }\r
- if(key == 68) /* Right arrow */ \r
- { \r
- buffer[bufpnt].key = key; \r
- printf("\033[1D"); \r
- }\r
- \r
- bufpnt += 1; \r
- } \r
- \r
- \r
- \r
- /* The Enter key exits. Enter is 10 decimal */ \r
- else if(key == 10) \r
- { \r
- puts("\n"); \r
- int j ; \r
- /* Print the array of structs. */ \r
- for (j=0; j<bufpnt; j++) \r
- { \r
- printf("Fnkey: %d ", buffer[j].fnkey ) ; \r
- printf("Ctrl: %d ", buffer[j].ctrl ) ; \r
- printf("Alt: %d ", buffer[j].alt ) ; \r
- printf("Shf: %d ", buffer[j].shf ) ; \r
- printf("Esc: %d ", buffer[j].esc ) ; \r
- printf("Lbr: %d ", buffer[j].lbr ) ; \r
- printf("Key: %d \n", buffer[j].key ) ; \r
- } \r
- \r
- break; \r
- } /* Key = Enter */ \r
- } \r
- \r
- return 0;\r
-} \r
-\r
-\r
-\r
-\r
+++ /dev/null
-\r
-\r
-/* pdmenu.c */ \r
-/* This code is aimed at helping those who would like to */ \r
-/* create menus without using the curses library. */ \r
-/* It creates a count variable (which could be used to */ \r
-/* keep track of which item is highlighted). Using the */ \r
-/* up and down arrow keys increments and decrements the */ \r
-/* count variable. Finally, when you press Enter, the */ \r
-/* value of the count variable is printed and the program */ \r
-/* exits. */ \r
-/* This code is released to the public domain. */ \r
-/* "Share and enjoy...." ;) */ \r
-\r
-\r
-#include <string.h> \r
-#include <stdio.h> \r
-#include <termios.h> /* For getch() */ \r
-\r
-/* This implementation of getch() is from here - */ \r
-/* http://wesley.vidiqatch.org/ */ \r
-/* Thanks, Wesley! */ \r
-static struct termios old, new;\r
-\r
-/* Initialize new terminal i/o settings */\r
-void initTermios(int echo) {\r
- tcgetattr(0, &old); /* grab old terminal i/o settings */\r
- new = old; /* make new settings same as old settings */\r
- new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
- new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
- tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
-}\r
-\r
-\r
-/* Restore old terminal i/o settings */\r
-void resetTermios(void) {\r
- tcsetattr(0, TCSANOW, &old);\r
-}\r
-\r
-\r
-/* Read 1 character - echo defines echo mode */\r
-char getch_(int echo) {\r
- char ch;\r
- initTermios(echo);\r
- ch = getchar();\r
- resetTermios();\r
- return ch;\r
-}\r
-\r
-\r
-/* Read 1 character without echo */\r
-char getch(void) {\r
- return getch_(0);\r
-}\r
-\r
-\r
-/* Read 1 character with echo */\r
-char getche(void) {\r
- return getch_(1);\r
-} \r
-\r
-\r
-\r
-\r
-int main(void)\r
-{\r
- \r
- printf("Public Domain Menu Program \n"); \r
- printf("\nUse the up and down arrow keys then press Enter\n"); \r
- \r
- int menunum = 0; \r
- \r
- while(1) \r
- { \r
- \r
- int key = getch(); \r
- \r
- /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
- /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
- /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
- /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
- if(key == 27) \r
- { key = getch(); \r
- if(key == 91) \r
- key = getch(); \r
- if(key == 65) \r
- { puts("You pressed up arrow! \n"); \r
- menunum-=1; \r
- printf("Menunum is now %d \n", menunum); \r
- } \r
- else if(key == 66) \r
- { puts("You pressed down arrow! \n"); \r
- menunum+=1; \r
- printf("Menunum is now %d \n", menunum); \r
- } \r
- else if(key == 67) \r
- { puts("You pressed right arrow! \n"); \r
- } \r
- else if(key == 68) \r
- { puts("You pressed left arrow! \n"); \r
- } \r
- }\r
- \r
- /* A few other keys (for testing purposes ) */ \r
- else if(key == 97) \r
- { puts("You pressed the \"a\" key! \n"); \r
- } \r
- else if(key == 98) \r
- { puts("You pressed the \"b\" key! \n"); \r
- } \r
- else if(key == 99) \r
- { puts("You pressed the \"c\" key! \n"); \r
- }\r
- else if(key == 100) \r
- { puts("You pressed the \"d\" key! \n"); \r
- } \r
- \r
- \r
- /* The Enter key exits. Enter is 10 decimal */ \r
- else if(key == 10) \r
- { printf("You pressed ENTER! You chose item %d \n", menunum); \r
- break; } \r
- } \r
- \r
- return 0;\r
-} \r
-\r
-\r
-\r
-\r
+++ /dev/null
-\r
-\r
-/* pdmenu.c */ \r
-/* This code is aimed at helping those who would like to */ \r
-/* create menus without using the curses library. */ \r
-/* It creates a count variable (which could be used to */ \r
-/* keep track of which item is highlighted). Using the */ \r
-/* up and down arrow keys increments and decrements the */ \r
-/* count variable. Finally, when you press Enter, the */ \r
-/* value of the count variable is printed and the program */ \r
-/* exits. */ \r
-/* This code is released to the public domain. */ \r
-/* "Share and enjoy...." ;) */ \r
-\r
-\r
-#include <string.h> \r
-#include <stdio.h> \r
-#include <termios.h> /* For getch() */ \r
-\r
-/* This implementation of getch() is from here - */ \r
-/* http://wesley.vidiqatch.org/ */ \r
-/* Thanks, Wesley! */ \r
-static struct termios old, new;\r
-\r
-/* Initialize new terminal i/o settings */\r
-void initTermios(int echo) {\r
- tcgetattr(0, &old); /* grab old terminal i/o settings */\r
- new = old; /* make new settings same as old settings */\r
- new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
- new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
- tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
-}\r
-\r
-\r
-/* Restore old terminal i/o settings */\r
-void resetTermios(void) {\r
- tcsetattr(0, TCSANOW, &old);\r
-}\r
-\r
-\r
-/* Read 1 character - echo defines echo mode */\r
-char getch_(int echo) {\r
- char ch;\r
- initTermios(echo);\r
- ch = getchar();\r
- resetTermios();\r
- return ch;\r
-}\r
-\r
-\r
-/* Read 1 character without echo */\r
-char getch(void) {\r
- return getch_(0);\r
-}\r
-\r
-\r
-/* Read 1 character with echo */\r
-char getche(void) {\r
- return getch_(1);\r
-} \r
-\r
-\r
-\r
-/* Helper function, to let us see if a .history file */ \r
-/* exists in the current directory. */ \r
-int fexists(char *fname)\r
-{ \r
-\r
- FILE *fptr ; \r
- \r
- fptr = fopen(fname, "r") ; \r
- \r
- if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
- \r
- fclose(fptr); \r
- return 0; /* File DOES exist in dir. */ \r
-\r
-} \r
-\r
-\r
-\r
-int main(void)\r
-{\r
- \r
- printf("Public Domain Menu Program \n"); \r
- printf("\nUse the up and down arrow keys then press Enter\n"); \r
- \r
- int menunum = 0; \r
- \r
- /* Buffer */ \r
- char buffer[80] ; \r
- \r
- /* Buffer "pointer" */ \r
- int bufpnt = 0; \r
- \r
- \r
- /* Test for existence of history file. */ \r
- int exists; \r
- exists = fexists(".history"); \r
- printf("Result: %d \n", exists); \r
- \r
- while(1) \r
- { \r
- \r
- int key = getch(); \r
- \r
- /* Printable chars. */ \r
- if ( (key >= 32) && (key <= 126) ) \r
- { \r
- buffer[bufpnt] = key; \r
- bufpnt += 1; \r
- } \r
- \r
- /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
- /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
- /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
- /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
- else if(key == 27) \r
- { key = getch(); \r
- if(key == 91) \r
- key = getch(); \r
- if(key == 65) \r
- { puts("You pressed up arrow! \n"); \r
- menunum-=1; \r
- printf("Menunum is now %d \n", menunum); \r
- } \r
- else if(key == 66) \r
- { puts("You pressed down arrow! \n"); \r
- menunum+=1; \r
- printf("Menunum is now %d \n", menunum); \r
- } \r
- else if(key == 67) \r
- { puts("You pressed right arrow! \n"); \r
- } \r
- else if(key == 68) \r
- { puts("You pressed left arrow! \n"); \r
- } \r
- }\r
- \r
- /* A few other keys (for testing purposes ) */ \r
- \r
- /* \r
- else if(key == 97) \r
- { puts("You pressed the \"a\" key! \n"); \r
- } \r
- else if(key == 98) \r
- { puts("You pressed the \"b\" key! \n"); \r
- } \r
- else if(key == 99) \r
- { puts("You pressed the \"c\" key! \n"); \r
- }\r
- else if(key == 100) \r
- { puts("You pressed the \"d\" key! \n"); \r
- } \r
- */ \r
- \r
- \r
- /* The Enter key exits. Enter is 10 decimal */ \r
- else if(key == 10) \r
- { printf("You pressed ENTER! You chose item %d \n", menunum); \r
- printf("Buffer is %s \n", buffer) ; \r
- break; } \r
- } \r
- \r
- return 0;\r
-} \r
-\r
-\r
-\r
-\r
+++ /dev/null
-\r
-\r
-/* pdmenu.c */ \r
-/* This code is aimed at helping those who would like to */ \r
-/* create menus without using the curses library. */ \r
-/* It creates a count variable (which could be used to */ \r
-/* keep track of which item is highlighted). Using the */ \r
-/* up and down arrow keys increments and decrements the */ \r
-/* count variable. Finally, when you press Enter, the */ \r
-/* value of the count variable is printed and the program */ \r
-/* exits. */ \r
-/* This code is released to the public domain. */ \r
-/* "Share and enjoy...." ;) */ \r
-\r
-\r
-#include <string.h> \r
-#include <stdio.h> \r
-#include <termios.h> /* For getch() */ \r
-\r
-/* This implementation of getch() is from here - */ \r
-/* http://wesley.vidiqatch.org/ */ \r
-/* Thanks, Wesley! */ \r
-static struct termios old, new;\r
-\r
-/* Initialize new terminal i/o settings */\r
-void initTermios(int echo) {\r
- tcgetattr(0, &old); /* grab old terminal i/o settings */\r
- new = old; /* make new settings same as old settings */\r
- new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
- new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
- tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
-}\r
-\r
-\r
-/* Restore old terminal i/o settings */\r
-void resetTermios(void) {\r
- tcsetattr(0, TCSANOW, &old);\r
-}\r
-\r
-\r
-/* Read 1 character - echo defines echo mode */\r
-char getch_(int echo) {\r
- char ch;\r
- initTermios(echo);\r
- ch = getchar();\r
- resetTermios();\r
- return ch;\r
-}\r
-\r
-\r
-/* Read 1 character without echo */\r
-char getch(void) {\r
- return getch_(0);\r
-}\r
-\r
-\r
-/* Read 1 character with echo */\r
-char getche(void) {\r
- return getch_(1);\r
-} \r
-\r
-\r
-\r
-/* Helper function, to let us see if a .history file */ \r
-/* exists in the current directory. */ \r
-int fexists(char *fname)\r
-{ \r
-\r
- FILE *fptr ; \r
- \r
- fptr = fopen(fname, "r") ; \r
- \r
- if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
- \r
- fclose(fptr); \r
- return 0; /* File DOES exist in dir. */ \r
-\r
-} \r
-\r
-\r
- /* Struct to store key sequences */ \r
-typedef struct { \r
- int fnkey; \r
- int ctrl; \r
- int alt ; \r
- int shf ; \r
- int esc ; \r
- int lbr ; /* For left-bracket ([) of escape sequences */ \r
- int key; \r
- } keyseq ; \r
-\r
-\r
-\r
-\r
-\r
-int main(void)\r
-{\r
- \r
- printf("Public Domain Menu Program \n"); \r
- \r
- \r
- keyseq myseq; \r
- \r
- \r
- /* Buffer */ \r
- keyseq buffer[80] ; \r
- \r
- /* Buffer "pointer" */ \r
- int bufpnt = 0; \r
- \r
- \r
- /* Test for existence of history file. */ \r
- int exists; \r
- exists = fexists(".history"); \r
- printf("Result: %d \n", exists); \r
- \r
- while(1) \r
- { \r
- \r
- int key = getch(); \r
- \r
- /* Printable chars. */ \r
- if ( (key >= 32) && (key <= 126) ) \r
- { \r
- myseq.key = key; \r
- buffer[bufpnt] = myseq; \r
- bufpnt += 1; \r
- } \r
- \r
- /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
- /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
- /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
- /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
- /* Function keys. */ \r
- /* F2 is 27, 79, 81. */ \r
- /* F3 is 27, 79, 82. */ \r
- /* F4 is 27, 79, 83. */ \r
- \r
- \r
- else if(key == 27) \r
- { \r
- myseq.key = key; \r
- buffer[bufpnt] = myseq; \r
- bufpnt += 1; \r
- key = getch(); \r
- if(key == 91) \r
- myseq.key = key; \r
- buffer[bufpnt] = myseq; \r
- bufpnt += 1; \r
- key = getch(); \r
- if( (key >= 65) && (key <= 68) ) \r
- { \r
- myseq.key = key; \r
- buffer[bufpnt] = myseq; \r
- bufpnt += 1; \r
- } \r
- }\r
- \r
- \r
- \r
- /* The Enter key exits. Enter is 10 decimal */ \r
- else if(key == 10) \r
- { \r
- int j ; \r
- /* Print the array of structs. */ \r
- for (j=0; j<10; j++) \r
- { \r
- printf("Fnkey: %d ", buffer[j].fnkey ) ; \r
- printf("Ctrl: %d ", buffer[j].ctrl ) ; \r
- printf("Alt: %d ", buffer[j].alt ) ; \r
- printf("Shf: %d ", buffer[j].shf ) ; \r
- printf("Esc: %d ", buffer[j].esc ) ; \r
- printf("Lbr: %d ", buffer[j].lbr ) ; \r
- printf("Key: %d \n", buffer[j].key ) ; \r
- } \r
- \r
- break; \r
- } /* Key = Enter */ \r
- } \r
- \r
- return 0;\r
-} \r
-\r
-\r
-\r
-\r
+++ /dev/null
-\r
-\r
-/* pd_readline.c */ \r
-/* Status (as at 26th Aug 2012) : useful progress. */ \r
-/* Keystroke sequences (along with the special flags */ \r
-/* like Esc, Ctrl, Alt etc are now stored in a buffer */ \r
-/* ( an array of structs ). */ \r
-/* It will still be some time before this is a REAL */ \r
-/* readline, but we are "on the way"...... */ \r
-/* This code is released to the public domain. */ \r
-/* "Share and enjoy...." ;) */ \r
-\r
-\r
-#include <string.h> \r
-#include <stdio.h> \r
-#include <termios.h> /* For getch() */ \r
-\r
-/* This implementation of getch() is from here - */ \r
-/* http://wesley.vidiqatch.org/ */ \r
-/* Thanks, Wesley! */ \r
-static struct termios old, new;\r
-\r
-/* Initialize new terminal i/o settings */\r
-void initTermios(int echo) {\r
- tcgetattr(0, &old); /* grab old terminal i/o settings */\r
- new = old; /* make new settings same as old settings */\r
- new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
- new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
- tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
-}\r
-\r
-\r
-/* Restore old terminal i/o settings */\r
-void resetTermios(void) {\r
- tcsetattr(0, TCSANOW, &old);\r
-}\r
-\r
-\r
-/* Read 1 character - echo defines echo mode */\r
-char getch_(int echo) {\r
- char ch;\r
- initTermios(echo);\r
- ch = getchar();\r
- resetTermios();\r
- return ch;\r
-}\r
-\r
-\r
-/* Read 1 character without echo */\r
-char getch(void) {\r
- return getch_(0);\r
-}\r
-\r
-\r
-/* Read 1 character with echo */\r
-char getche(void) {\r
- return getch_(1);\r
-} \r
-\r
-\r
-\r
-/* Helper function, to let us see if a .history file */ \r
-/* exists in the current directory. */ \r
-int fexists(char *fname)\r
-{ \r
-\r
- FILE *fptr ; \r
- \r
- fptr = fopen(fname, "r") ; \r
- \r
- if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
- \r
- fclose(fptr); \r
- return 0; /* File DOES exist in dir. */ \r
-\r
-} \r
-\r
-\r
- /* Struct to store key sequences */ \r
-typedef struct { \r
- int fnkey; \r
- int ctrl; \r
- int alt ; \r
- int shf ; \r
- int esc ; \r
- int lbr ; /* For left-bracket ([) of escape sequences */ \r
- int key; \r
- } keyseq ; \r
-\r
-\r
-\r
-\r
-\r
-int main(void)\r
-{\r
- \r
- printf("Public Domain Readline \n"); \r
- printf("NOTE! - at the moment, we are using \n"); \r
- printf("NON-echoing reads, storing the keystrokes \n"); \r
- printf("in a buffer \n"); \r
- \r
- \r
- /* Buffer - an array of keyseq structs. */ \r
- /* Note - now that we store the keystrokes in here, */ \r
- /* we can look at the various flags and decide whether to */ \r
- /* "echo" the key (as normal) or suppress it (as with an */ \r
- /* arrow key). */ \r
- keyseq buffer[80] ; \r
- \r
- /* Buffer "pointer" */ \r
- int bufpnt = 0; \r
- \r
- \r
- /* Test for existence of history file. */ \r
- int exists; \r
- exists = fexists(".history"); \r
- printf("Result: %d \n", exists); \r
- \r
- while(1) \r
- { \r
- \r
- int key = getch(); \r
- \r
- /* Printable chars. */ \r
- if ( (key >= 32) && (key <= 126) ) \r
- { \r
- buffer[bufpnt].key = key; \r
- bufpnt += 1; \r
- } \r
- \r
- /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
- /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
- /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
- /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
- /* Function keys. */ \r
- /* F2 is 27, 79, 81. */ \r
- /* F3 is 27, 79, 82. */ \r
- /* F4 is 27, 79, 83. */ \r
- \r
- \r
- else if(key == 27) \r
- { \r
- \r
- buffer[bufpnt].esc = 1; \r
- bufpnt += 1; \r
- key = getch(); \r
- if(key == 91) \r
- buffer[bufpnt].lbr = 1; \r
- bufpnt += 1; \r
- key = getch(); \r
- if( (key >= 65) && (key <= 68) ) \r
- { \r
- buffer[bufpnt].key = key; \r
- bufpnt += 1; \r
- } \r
- }\r
- \r
- \r
- \r
- /* The Enter key exits. Enter is 10 decimal */ \r
- else if(key == 10) \r
- { \r
- int j ; \r
- /* Print the array of structs. */ \r
- for (j=0; j<20; j++) \r
- { \r
- printf("Fnkey: %d ", buffer[j].fnkey ) ; \r
- printf("Ctrl: %d ", buffer[j].ctrl ) ; \r
- printf("Alt: %d ", buffer[j].alt ) ; \r
- printf("Shf: %d ", buffer[j].shf ) ; \r
- printf("Esc: %d ", buffer[j].esc ) ; \r
- printf("Lbr: %d ", buffer[j].lbr ) ; \r
- printf("Key: %d \n", buffer[j].key ) ; \r
- } \r
- \r
- break; \r
- } /* Key = Enter */ \r
- } \r
- \r
- return 0;\r
-} \r
-\r
-\r
-\r
-\r
+++ /dev/null
-\r
-\r
-/* pd_readline.c */ \r
-/* Status (as at 26th Aug 2012) : useful progress. */ \r
-/* Keystroke sequences (along with the special flags */ \r
-/* like Esc, Ctrl, Alt etc are now stored in a buffer */ \r
-/* ( an array of structs ). */ \r
-/* It will still be some time before this is a REAL */ \r
-/* readline, but we are "on the way"...... */ \r
-/* This code is released to the public domain. */ \r
-/* "Share and enjoy...." ;) */ \r
-\r
-\r
-#include <string.h> \r
-#include <stdio.h> \r
-\r
-\r
-/* Helper function, to let us see if a .history file */ \r
-/* exists in the current directory. */ \r
-int fexists(char *fname)\r
-{ \r
-\r
- FILE *fptr ; \r
- \r
- fptr = fopen(fname, "r") ; \r
- \r
- if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
- \r
- fclose(fptr); \r
- return 0; /* File DOES exist in dir. */ \r
-\r
-} \r
-\r
-\r
- /* Struct to store key sequences */ \r
-typedef struct { \r
- int fnkey; \r
- int ctrl; \r
- int alt ; \r
- int shf ; \r
- int esc ; \r
- int lbr ; /* For left-bracket ([) of escape sequences */ \r
- int key; \r
- } keyseq ; \r
-\r
-\r
-\r
-\r
-\r
-int main(void)\r
-{\r
- \r
- printf("Public Domain Readline \n"); \r
- printf("NOTE! - at the moment, we are using \n"); \r
- printf("NON-echoing reads, storing the keystrokes \n"); \r
- printf("in a buffer \n"); \r
- \r
- \r
- /* Buffer - an array of keyseq structs. */ \r
- /* Note - now that we store the keystrokes in here, */ \r
- /* we can look at the various flags and decide whether to */ \r
- /* "echo" the key (as normal) or suppress it (as with an */ \r
- /* arrow key). */ \r
- keyseq buffer[80] ; \r
- \r
- /* Buffer "pointer" */ \r
- int bufpnt = 0; \r
- \r
- \r
- /* Test for existence of history file. */ \r
- int exists; \r
- exists = fexists(".history"); \r
- printf("Result: %d \n", exists); \r
- \r
- while(1) \r
- { \r
- \r
- int key = getchar(); \r
- \r
- /* Printable chars. */ \r
- if ( (key >= 32) && (key <= 126) ) \r
- { \r
- putchar(key); \r
- buffer[bufpnt].key = key; \r
- bufpnt += 1; \r
- } \r
- \r
- /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
- /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
- /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
- /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
- /* Function keys. */ \r
- /* F2 is 27, 79, 81. */ \r
- /* F3 is 27, 79, 82. */ \r
- /* F4 is 27, 79, 83. */ \r
- \r
- \r
- else if(key == 27) \r
- { \r
- buffer[bufpnt].esc = 1; \r
- key = getchar(); \r
- if(key == 91) \r
- buffer[bufpnt].lbr = 1; \r
- key = getchar(); \r
- if( (key >= 65) && (key <= 68) ) \r
- { \r
- buffer[bufpnt].key = key; \r
- } \r
- bufpnt += 1; \r
- } \r
- \r
- \r
- \r
- /* The Enter key exits. Enter is 10 decimal */ \r
- else if(key == 10) \r
- { \r
- int j ; \r
- /* Print the array of structs. */ \r
- for (j=0; j<10; j++) \r
- { \r
- printf("Fnkey: %d ", buffer[j].fnkey ) ; \r
- printf("Ctrl: %d ", buffer[j].ctrl ) ; \r
- printf("Alt: %d ", buffer[j].alt ) ; \r
- printf("Shf: %d ", buffer[j].shf ) ; \r
- printf("Esc: %d ", buffer[j].esc ) ; \r
- printf("Lbr: %d ", buffer[j].lbr ) ; \r
- printf("Key: %d \n", buffer[j].key ) ; \r
- } \r
- \r
- break; \r
- } /* Key = Enter */ \r
- } \r
- \r
- return 0;\r
-} \r
-\r
-\r
-\r
-\r
+++ /dev/null
-\r
-\r
-/* pd_readline.c */ \r
-/* Status (as at 26th Aug 2012) : useful progress. */ \r
-/* Keystroke sequences (along with the special flags */ \r
-/* like Esc, Ctrl, Alt etc are now stored in a buffer */ \r
-/* ( an array of structs ). */ \r
-/* It will still be some time before this is a REAL */ \r
-/* readline, but we are "on the way"...... */ \r
-/* This code is released to the public domain. */ \r
-/* "Share and enjoy...." ;) */ \r
-\r
-\r
-#include <string.h> \r
-#include <stdio.h> \r
-\r
-\r
-/* Helper function, to let us see if a .history file */ \r
-/* exists in the current directory. */ \r
-int fexists(char *fname)\r
-{ \r
-\r
- FILE *fptr ; \r
- \r
- fptr = fopen(fname, "r") ; \r
- \r
- if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
- \r
- fclose(fptr); \r
- return 0; /* File DOES exist in dir. */ \r
-\r
-} \r
-\r
-\r
- /* Struct to store key sequences */ \r
-typedef struct { \r
- int fnkey; \r
- int ctrl; \r
- int alt ; \r
- int shf ; \r
- int esc ; \r
- int lbr ; /* For left-bracket ([) of escape sequences */ \r
- int key; \r
- } keyseq ; \r
-\r
-\r
-/* A custom getchar to test the character type. */ \r
-int mygetchar(void) \r
-{\r
- int ch = getchar(); \r
- if ( (ch >= 32) && (ch <= 126) ) \r
- { \r
- putchar(ch); \r
- return ch; \r
- } \r
- else \r
- { \r
- return ch; \r
- } \r
- \r
-}\r
-\r
-\r
-\r
-int main(void)\r
-{\r
- \r
- printf("Public Domain Readline \n"); \r
- printf("NOTE! - at the moment, we are using \n"); \r
- printf("NON-echoing reads, storing the keystrokes \n"); \r
- printf("in a buffer \n"); \r
- \r
- \r
- /* Buffer - an array of keyseq structs. */ \r
- /* Note - now that we store the keystrokes in here, */ \r
- /* we can look at the various flags and decide whether to */ \r
- /* "echo" the key (as normal) or suppress it (as with an */ \r
- /* arrow key). */ \r
- keyseq buffer[80] ; \r
- \r
- /* Buffer "pointer" */ \r
- int bufpnt = 0; \r
- \r
- \r
- /* Test for existence of history file. */ \r
- int exists; \r
- exists = fexists(".history"); \r
- printf("Result: %d \n", exists); \r
- \r
- while(1) \r
- { \r
- \r
- int key = mygetchar(); \r
- \r
- /* Printable chars. */ \r
- if ( (key >= 32) && (key <= 126) ) \r
- { \r
- putchar(key); \r
- buffer[bufpnt].key = key; \r
- bufpnt += 1; \r
- } \r
- \r
- /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
- /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
- /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
- /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
- /* Function keys. */ \r
- /* F2 is 27, 79, 81. */ \r
- /* F3 is 27, 79, 82. */ \r
- /* F4 is 27, 79, 83. */ \r
- \r
- \r
- else if(key == 27) \r
- { \r
- buffer[bufpnt].esc = 1; \r
- key = mygetchar(); \r
- if(key == 91) \r
- buffer[bufpnt].lbr = 1; \r
- key = mygetchar(); \r
- if( (key >= 65) && (key <= 68) ) \r
- { \r
- buffer[bufpnt].key = key; \r
- } \r
- bufpnt += 1; \r
- } \r
- \r
- \r
- \r
- /* The Enter key exits. Enter is 10 decimal */ \r
- else if(key == 10) \r
- { \r
- int j ; \r
- /* Print the array of structs. */ \r
- for (j=0; j<10; j++) \r
- { \r
- printf("Fnkey: %d ", buffer[j].fnkey ) ; \r
- printf("Ctrl: %d ", buffer[j].ctrl ) ; \r
- printf("Alt: %d ", buffer[j].alt ) ; \r
- printf("Shf: %d ", buffer[j].shf ) ; \r
- printf("Esc: %d ", buffer[j].esc ) ; \r
- printf("Lbr: %d ", buffer[j].lbr ) ; \r
- printf("Key: %d \n", buffer[j].key ) ; \r
- } \r
- \r
- break; \r
- } /* Key = Enter */ \r
- } \r
- \r
- return 0;\r
-} \r
-\r
-\r
-\r
-\r
+++ /dev/null
-\r
-\r
-/* pd_readline2.c */ \r
-/* Status (as at 26th Aug 2012) : useful progress. */ \r
-/* Keystroke sequences (along with the special flags */ \r
-/* like Esc, Ctrl, Alt etc are now stored in a buffer */ \r
-/* ( an array of structs ). */ \r
-\r
-/* The code can now distinguish between a printable key */ \r
-/* and a key that should not be printed. */ \r
-\r
-/* It will still be some time before this is a REAL */ \r
-/* readline, but we are "on the way"...... */ \r
-/* This code is released to the public domain. */ \r
-/* "Share and enjoy...." ;) */ \r
-\r
-\r
-#include <string.h> \r
-#include <stdio.h> \r
-#include <termios.h> /* For getch() */ \r
-\r
-/* This implementation of getch() is from here - */ \r
-/* http://wesley.vidiqatch.org/ */ \r
-/* Thanks, Wesley! */ \r
-static struct termios old, new;\r
-\r
-/* Initialize new terminal i/o settings */\r
-void initTermios(int echo) {\r
- tcgetattr(0, &old); /* grab old terminal i/o settings */\r
- new = old; /* make new settings same as old settings */\r
- new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
- new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
- tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
-}\r
-\r
-\r
-/* Restore old terminal i/o settings */\r
-void resetTermios(void) {\r
- tcsetattr(0, TCSANOW, &old);\r
-}\r
-\r
-\r
-/* Read 1 character - echo defines echo mode */\r
-char getch_(int echo) {\r
- char ch;\r
- initTermios(echo);\r
- ch = getchar();\r
- resetTermios();\r
- return ch;\r
-}\r
-\r
-\r
-/* Read 1 character without echo */\r
-char getch(void) {\r
- return getch_(0);\r
-}\r
-\r
-\r
-/* Read 1 character with echo */\r
-char getche(void) {\r
- return getch_(1);\r
-} \r
-\r
-\r
-\r
-/* Helper function, to let us see if a .history file */ \r
-/* exists in the current directory. */ \r
-int fexists(char *fname)\r
-{ \r
-\r
- FILE *fptr ; \r
- \r
- fptr = fopen(fname, "r") ; \r
- \r
- if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
- \r
- fclose(fptr); \r
- return 0; /* File DOES exist in dir. */ \r
-\r
-} \r
-\r
-\r
- /* Struct to store key sequences */ \r
-typedef struct { \r
- int fnkey; \r
- int ctrl; \r
- int alt ; \r
- int shf ; \r
- int esc ; \r
- int lbr ; /* For left-bracket ([) of escape sequences */ \r
- int key; \r
- } keyseq ; \r
-\r
-\r
-\r
-\r
-\r
-int main(void)\r
-{\r
- \r
- printf("Public Domain Readline \n"); \r
- \r
- /* Buffer - an array of keyseq structs. */ \r
- /* Note - now that we store the keystrokes in here, */ \r
- /* we can look at the various flags and decide whether to */ \r
- /* "echo" the key (as normal) or suppress it (as with an */ \r
- /* arrow key). */ \r
- keyseq buffer[80] ; \r
- \r
- /* Buffer "pointer" */ \r
- int bufpnt = 0; \r
- \r
- \r
- /* Test for existence of history file. */ \r
- int exists; \r
- exists = fexists(".history"); \r
- printf("Result: %d \n", exists); \r
- \r
- while(1) \r
- { \r
- \r
- int key = getch(); \r
- \r
- /* Printable chars. */ \r
- if ( (key >= 32) && (key <= 126) ) \r
- { \r
- /* We have a printable key so print it. */ \r
- putchar(key); \r
- buffer[bufpnt].key = key; \r
- bufpnt += 1; \r
- } \r
- \r
- /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
- /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
- /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
- /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
- /* Function keys. */ \r
- /* F2 is 27, 79, 81. */ \r
- /* F3 is 27, 79, 82. */ \r
- /* F4 is 27, 79, 83. */ \r
- \r
- \r
- else if(key == 27) \r
- { \r
- \r
- buffer[bufpnt].esc = 1; \r
- key = getch(); \r
- if(key == 91) \r
- buffer[bufpnt].lbr = 1; \r
- key = getch(); \r
- if( (key >= 65) && (key <= 68) ) \r
- { \r
- buffer[bufpnt].key = key; \r
- } \r
- bufpnt += 1; \r
- } \r
- \r
- \r
- \r
- /* The Enter key exits. Enter is 10 decimal */ \r
- else if(key == 10) \r
- { \r
- puts("\n"); \r
- int j ; \r
- /* Print the array of structs. */ \r
- for (j=0; j<20; j++) \r
- { \r
- printf("Fnkey: %d ", buffer[j].fnkey ) ; \r
- printf("Ctrl: %d ", buffer[j].ctrl ) ; \r
- printf("Alt: %d ", buffer[j].alt ) ; \r
- printf("Shf: %d ", buffer[j].shf ) ; \r
- printf("Esc: %d ", buffer[j].esc ) ; \r
- printf("Lbr: %d ", buffer[j].lbr ) ; \r
- printf("Key: %d \n", buffer[j].key ) ; \r
- } \r
- \r
- break; \r
- } /* Key = Enter */ \r
- } \r
- \r
- return 0;\r
-} \r
-\r
-\r
-\r
-\r
+++ /dev/null
-\r
-\r
-/* pd_readline2.c */ \r
-/* Status (as at 26th Aug 2012) : useful progress. */ \r
-/* Keystroke sequences (along with the special flags */ \r
-/* like Esc, Ctrl, Alt etc are now stored in a buffer */ \r
-/* ( an array of structs ). */ \r
-\r
-/* The code can now distinguish between a printable key */ \r
-/* and a key that should not be printed. */ \r
-\r
-/* Backspace key, and left and right arrow keys now work. */ \r
-\r
-/* It will still be some time before this is a REAL */ \r
-/* readline, but we are "on the way"...... */ \r
-/* This code is released to the public domain. */ \r
-/* "Share and enjoy...." ;) */ \r
-\r
-\r
-#include <string.h> \r
-#include <stdio.h> \r
-#include <termios.h> /* For getch() */ \r
-\r
-/* This implementation of getch() is from here - */ \r
-/* http://wesley.vidiqatch.org/ */ \r
-/* Thanks, Wesley! */ \r
-static struct termios old, new;\r
-\r
-/* Initialize new terminal i/o settings */\r
-void initTermios(int echo) {\r
- tcgetattr(0, &old); /* grab old terminal i/o settings */\r
- new = old; /* make new settings same as old settings */\r
- new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
- new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
- tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
-}\r
-\r
-\r
-/* Restore old terminal i/o settings */\r
-void resetTermios(void) {\r
- tcsetattr(0, TCSANOW, &old);\r
-}\r
-\r
-\r
-/* Read 1 character - echo defines echo mode */\r
-char getch_(int echo) {\r
- char ch;\r
- initTermios(echo);\r
- ch = getchar();\r
- resetTermios();\r
- return ch;\r
-}\r
-\r
-\r
-/* Read 1 character without echo */\r
-char getch(void) {\r
- return getch_(0);\r
-}\r
-\r
-\r
-/* Read 1 character with echo */\r
-char getche(void) {\r
- return getch_(1);\r
-} \r
-\r
-\r
-\r
-/* Helper function, to let us see if a .history file */ \r
-/* exists in the current directory. */ \r
-int fexists(char *fname)\r
-{ \r
-\r
- FILE *fptr ; \r
- \r
- fptr = fopen(fname, "r") ; \r
- \r
- if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
- \r
- fclose(fptr); \r
- return 0; /* File DOES exist in dir. */ \r
-\r
-} \r
-\r
-\r
- /* Struct to store key sequences */ \r
-typedef struct { \r
- int fnkey; \r
- int ctrl; \r
- int alt ; \r
- int shf ; \r
- int esc ; \r
- int lbr ; /* For left-bracket ([) of escape sequences */ \r
- int key; \r
- } keyseq ; \r
-\r
-\r
-\r
-\r
-\r
-int main(void)\r
-{\r
- \r
- printf("Public Domain Readline \n"); \r
- \r
- /* Buffer - an array of keyseq structs. */ \r
- /* Note - now that we store the keystrokes in here, */ \r
- /* we can look at the various flags and decide whether to */ \r
- /* "echo" the key (as normal) or suppress it (as with an */ \r
- /* arrow key). */ \r
- keyseq buffer[80] ; \r
- \r
- /* Buffer "pointer" */ \r
- int bufpnt = 0; \r
- \r
- \r
- /* Test for existence of history file. */ \r
- int exists; \r
- exists = fexists(".history"); \r
- printf("Result: %d \n", exists); \r
- \r
- while(1) \r
- { \r
- \r
- int key = getch(); \r
- \r
- /* Printable chars. */ \r
- if ( (key >= 32) && (key <= 126) ) \r
- { \r
- /* We have a printable key so print it. */ \r
- putchar(key); \r
- buffer[bufpnt].key = key; \r
- bufpnt += 1; \r
- } \r
- \r
- /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
- /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
- /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
- /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
- /* Function keys. */ \r
- /* F2 is 27, 79, 81. */ \r
- /* F3 is 27, 79, 82. */ \r
- /* F4 is 27, 79, 83. */ \r
- \r
- /* Backspace */ \r
- else if(key == 127) \r
- { \r
- buffer[bufpnt].key = key; \r
- /* Move 1 char to left */ \r
- printf("\033[1D");\r
- printf("\040"); \r
- printf("\033[1D"); \r
- bufpnt += 1; \r
- } \r
- \r
- else if(key == 27) \r
- { \r
- buffer[bufpnt].esc = 1; \r
- key = getch(); \r
- if(key == 91) \r
- buffer[bufpnt].lbr = 1; \r
- key = getch(); \r
- if(key == 65) /* Up arrow */ \r
- { \r
- buffer[bufpnt].key = key; \r
- } \r
- if(key == 66) /* Down arrow */ \r
- { \r
- buffer[bufpnt].key = key; \r
- } \r
- if(key == 67) /* Left arrow */ \r
- { \r
- buffer[bufpnt].key = key; \r
- printf("\033[1C"); \r
- }\r
- if(key == 68) /* Right arrow */ \r
- { \r
- buffer[bufpnt].key = key; \r
- printf("\033[1D"); \r
- }\r
- \r
- bufpnt += 1; \r
- } \r
- \r
- \r
- \r
- /* The Enter key exits. Enter is 10 decimal */ \r
- else if(key == 10) \r
- { \r
- puts("\n"); \r
- int j ; \r
- /* Print the array of structs. */ \r
- for (j=0; j<bufpnt; j++) \r
- { \r
- printf("Fnkey: %d ", buffer[j].fnkey ) ; \r
- printf("Ctrl: %d ", buffer[j].ctrl ) ; \r
- printf("Alt: %d ", buffer[j].alt ) ; \r
- printf("Shf: %d ", buffer[j].shf ) ; \r
- printf("Esc: %d ", buffer[j].esc ) ; \r
- printf("Lbr: %d ", buffer[j].lbr ) ; \r
- printf("Key: %d \n", buffer[j].key ) ; \r
- } \r
- \r
- break; \r
- } /* Key = Enter */ \r
- } \r
- \r
- return 0;\r
-} \r
-\r
-\r
-\r
-\r
+++ /dev/null
-\r
-\r
-/* pd_readline2.c */ \r
-/* Status (as at 26th Aug 2012) : useful progress. */ \r
-/* Keystroke sequences (along with the special flags */ \r
-/* like Esc, Ctrl, Alt etc are now stored in a buffer */ \r
-/* ( an array of structs ). */ \r
-\r
-/* The code can now distinguish between a printable key */ \r
-/* and a key that should not be printed. */ \r
-\r
-/* Backspace key, and left and right arrow keys now work. */ \r
-\r
-/* It will still be some time before this is a REAL */ \r
-/* readline, but we are "on the way"...... */ \r
-/* This code is released to the public domain. */ \r
-/* "Share and enjoy...." ;) */ \r
-\r
-\r
-#include <string.h> \r
-#include <stdio.h> \r
-#include <termios.h> /* For getch() */ \r
-\r
-/* This implementation of getch() is from here - */ \r
-/* http://wesley.vidiqatch.org/ */ \r
-/* Thanks, Wesley! */ \r
-static struct termios old, new;\r
-\r
-/* Initialize new terminal i/o settings */\r
-void initTermios(int echo) {\r
- tcgetattr(0, &old); /* grab old terminal i/o settings */\r
- new = old; /* make new settings same as old settings */\r
- new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
- new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
- tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
-}\r
-\r
-\r
-/* Restore old terminal i/o settings */\r
-void resetTermios(void) {\r
- tcsetattr(0, TCSANOW, &old);\r
-}\r
-\r
-\r
-/* Read 1 character - echo defines echo mode */\r
-char getch_(int echo) {\r
- char ch;\r
- initTermios(echo);\r
- ch = getchar();\r
- resetTermios();\r
- return ch;\r
-}\r
-\r
-\r
-/* Read 1 character without echo */\r
-char getch(void) {\r
- return getch_(0);\r
-}\r
-\r
-\r
-/* Read 1 character with echo */\r
-char getche(void) {\r
- return getch_(1);\r
-} \r
-\r
-\r
-\r
-/* Helper function, to let us see if a .history file */ \r
-/* exists in the current directory. */ \r
-int fexists(char *fname)\r
-{ \r
-\r
- FILE *fptr ; \r
- \r
- fptr = fopen(fname, "r") ; \r
- \r
- if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
- \r
- fclose(fptr); \r
- return 0; /* File DOES exist in dir. */ \r
-\r
-} \r
-\r
-\r
-/* Helper function to print escape sequences to terminal */ \r
-void prtseq(char *what) \r
-{ \r
- if (strcmp(what, "left") ) printf("\033[1D"); \r
- else if (strcmp(what, "right") ) printf("\033[1C"); \r
- else if (strcmp(what, "bs") ) \r
- printf("\033[1D");\r
- printf("\040"); \r
- printf("\033[1D"); \r
-} \r
-\r
-\r
-\r
-\r
- /* Struct to store key sequences */ \r
-typedef struct { \r
- int fnkey; \r
- int ctrl; \r
- int alt ; \r
- int shf ; \r
- int esc ; \r
- int lbr ; /* For left-bracket ([) of escape sequences */ \r
- int key; \r
- } keyseq ; \r
-\r
-\r
-\r
-\r
-\r
-int main(void)\r
-{\r
- \r
- printf("Public Domain Readline \n"); \r
- \r
- /* Buffer - an array of keyseq structs. */ \r
- /* Note - now that we store the keystrokes in here, */ \r
- /* we can look at the various flags and decide whether to */ \r
- /* "echo" the key (as normal) or suppress it (as with an */ \r
- /* arrow key). */ \r
- keyseq buffer[80] ; \r
- \r
- /* Buffer "pointer" */ \r
- int bufpnt = 0; \r
- \r
- \r
- /* Test for existence of history file. */ \r
- int exists; \r
- exists = fexists(".history"); \r
- printf("Result: %d \n", exists); \r
- \r
- while(1) \r
- { \r
- \r
- int key = getch(); \r
- \r
- /* Printable chars. */ \r
- if ( (key >= 32) && (key <= 126) ) \r
- { \r
- /* We have a printable key so print it. */ \r
- putchar(key); \r
- buffer[bufpnt].key = key; \r
- bufpnt += 1; \r
- } \r
- \r
- /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
- /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
- /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
- /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
- /* Function keys. */ \r
- /* F2 is 27, 79, 81. */ \r
- /* F3 is 27, 79, 82. */ \r
- /* F4 is 27, 79, 83. */ \r
- \r
- /* Backspace */ \r
- else if(key == 127) \r
- { \r
- buffer[bufpnt].key = key; \r
- /* Move 1 char to left */ \r
- prtseq("bs"); \r
- bufpnt += 1; \r
- } \r
- \r
- else if(key == 27) \r
- { \r
- buffer[bufpnt].esc = 1; \r
- key = getch(); \r
- if(key == 91) \r
- buffer[bufpnt].lbr = 1; \r
- key = getch(); \r
- if(key == 65) /* Up arrow */ \r
- { \r
- buffer[bufpnt].key = key; \r
- } \r
- if(key == 66) /* Down arrow */ \r
- { \r
- buffer[bufpnt].key = key; \r
- } \r
- if(key == 67) /* Left arrow */ \r
- { \r
- buffer[bufpnt].key = key; \r
- prtseq("left"); \r
- }\r
- if(key == 68) /* Right arrow */ \r
- { \r
- buffer[bufpnt].key = key; \r
- prtseq("right"); \r
- }\r
- \r
- bufpnt += 1; \r
- } \r
- \r
- \r
- \r
- /* The Enter key exits. Enter is 10 decimal */ \r
- else if(key == 10) \r
- { \r
- puts("\n"); \r
- int j ; \r
- /* Print the array of structs. */ \r
- for (j=0; j<bufpnt; j++) \r
- { \r
- printf("Fnkey: %d ", buffer[j].fnkey ) ; \r
- printf("Ctrl: %d ", buffer[j].ctrl ) ; \r
- printf("Alt: %d ", buffer[j].alt ) ; \r
- printf("Shf: %d ", buffer[j].shf ) ; \r
- printf("Esc: %d ", buffer[j].esc ) ; \r
- printf("Lbr: %d ", buffer[j].lbr ) ; \r
- printf("Key: %d \n", buffer[j].key ) ; \r
- } \r
- \r
- break; \r
- } /* Key = Enter */ \r
- } \r
- \r
- return 0;\r
-} \r
-\r
-\r
-\r
-\r
--- /dev/null
+
+
+
+/* readfile.c */
+
+/* Check that a file exists. */
+/* If it does, read it into an array and print it out. */
+
+
+#include <string.h>
+#include <stdio.h>
+
+
+
+/* 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;
+
+}
+
+
+
+
+
+
+
+
+
--- /dev/null
+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 ***
+
+++ /dev/null
-
-
-/* testkey.c */
-
-/* Prints the keycode for a given key */
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-
-
-
-int main (void)
-{
-
-int c;
-
-while( (c == getchar() ) )
-{
- printf("%d 0x%02X\n", c );
-}
-
-return 0;
-
-}