summaryrefslogtreecommitdiffstats
path: root/contrib/nvi/ip
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-11-01 06:45:43 +0000
committerpeter <peter@FreeBSD.org>1996-11-01 06:45:43 +0000
commit59cc89c2c2e686da3bdab2d5cfac4f33462d29fe (patch)
tree88f923c9c0be2e2a225a9b21716fd582de668b42 /contrib/nvi/ip
downloadFreeBSD-src-59cc89c2c2e686da3bdab2d5cfac4f33462d29fe.zip
FreeBSD-src-59cc89c2c2e686da3bdab2d5cfac4f33462d29fe.tar.gz
Import of nvi-1.79, minus a few bits that we dont need (eg: postscript
files, curses, db, regex etc that we already have). The other glue will follow shortly. Obtained from: Keith Bostic <bostic@bostic.com>
Diffstat (limited to 'contrib/nvi/ip')
-rw-r--r--contrib/nvi/ip/IP_INSTRUCTIONS41
-rw-r--r--contrib/nvi/ip/ip.h92
-rw-r--r--contrib/nvi/ip/ip_funcs.c443
-rw-r--r--contrib/nvi/ip/ip_main.c165
-rw-r--r--contrib/nvi/ip/ip_read.c307
-rw-r--r--contrib/nvi/ip/ip_screen.c87
-rw-r--r--contrib/nvi/ip/ip_term.c108
7 files changed, 1243 insertions, 0 deletions
diff --git a/contrib/nvi/ip/IP_INSTRUCTIONS b/contrib/nvi/ip/IP_INSTRUCTIONS
new file mode 100644
index 0000000..7745c88
--- /dev/null
+++ b/contrib/nvi/ip/IP_INSTRUCTIONS
@@ -0,0 +1,41 @@
+1: Add:
+ -DRUNNING_IP
+
+ to the Makefile CFLAGS line and rebuild cl_main.o if it's already
+ been compiled.
+
+2: Add:
+
+ IPOBJS= ip_funcs.o ip_main.o ip_read.o ip_screen.o ip_term.o
+
+ after the other object lists in the Makefile.
+
+3: Add
+ $(IPOBJS)
+
+ to the end of the NVIALL= line in the Makefile.
+
+4: Add:
+
+ # Vi IP sources.
+ ip_funcs.o: $(srcdir)/ip/ip_funcs.c
+ $(CC) $(CFLAGS) $?
+ ip_main.o: $(srcdir)/ip/ip_main.c
+ $(CC) $(CFLAGS) $?
+ ip_read.o: $(srcdir)/ip/ip_read.c
+ $(CC) $(CFLAGS) $?
+ ip_screen.o: $(srcdir)/ip/ip_screen.c
+ $(CC) $(CFLAGS) $?
+ ip_term.o: $(srcdir)/ip/ip_term.c
+ $(CC) $(CFLAGS) $?
+
+ at the end of the Makefile.
+
+5: Remove cl_main.o if it exists, and make nvi.
+
+6: Go to ip_cl and change the entries in the Makefile to reflect
+ where the nvi binary was just built.
+
+7: Build ip_cl.
+
+8: Enter ip_cl and you should be running vi over a pipe.
diff --git a/contrib/nvi/ip/ip.h b/contrib/nvi/ip/ip.h
new file mode 100644
index 0000000..f7798c3
--- /dev/null
+++ b/contrib/nvi/ip/ip.h
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)ip.h 8.3 (Berkeley) 10/13/96
+ */
+
+typedef struct _ip_private {
+ int i_fd; /* Input file descriptor. */
+ int o_fd; /* Output file descriptor. */
+
+ size_t row; /* Current row. */
+ size_t col; /* Current column. */
+
+ size_t iblen; /* Input buffer length. */
+ size_t iskip; /* Returned input buffer. */
+ char ibuf[256]; /* Input buffer. */
+
+#define IP_SCR_VI_INIT 0x0001 /* Vi screen initialized. */
+ u_int32_t flags;
+} IP_PRIVATE;
+
+#define IPP(sp) ((IP_PRIVATE *)((sp)->gp->ip_private))
+#define GIPP(gp) ((IP_PRIVATE *)((gp)->ip_private))
+
+/* The screen line relative to a specific window. */
+#define RLNO(sp, lno) (sp)->woff + (lno)
+
+/*
+ * The IP protocol consists of frames, each containing:
+ *
+ * <IPO_><object>
+ *
+ * XXX
+ * We should have a marking byte, 0xaa to delimit frames.
+ *
+ */
+#define IPO_CODE 1 /* An event specification. */
+#define IPO_INT 2 /* 4-byte, network order integer. */
+#define IPO_STR 3 /* IPO_INT: followed by N bytes. */
+
+#define IPO_CODE_LEN 1
+#define IPO_INT_LEN 4
+
+/* A structure that can hold the information for any frame. */
+typedef struct _ip_buf {
+ int code; /* Event code. */
+ const char *str; /* String. */
+ size_t len; /* String length. */
+ u_int32_t val1; /* First value. */
+ u_int32_t val2; /* Second value. */
+} IP_BUF;
+
+/*
+ * Screen/editor IP_CODE's.
+ *
+ * The program structure depends on the event loop being able to return
+ * IPO_EOF/IPOE_ERR multiple times -- eventually enough things will end
+ * due to the events that vi will reach the command level for the screen,
+ * at which point the exit flags will be set and vi will exit.
+ *
+ * IP events sent from the screen to vi.
+ */
+#define IPO_EOF 1 /* End of input (NOT ^D). */
+#define IPO_ERR 2 /* Input error. */
+#define IPO_INTERRUPT 3 /* Interrupt. */
+#define IPO_QUIT 4 /* Quit. */
+#define IPO_RESIZE 5 /* Screen resize: IPO_INT, IPO_INT. */
+#define IPO_SIGHUP 6 /* SIGHUP. */
+#define IPO_SIGTERM 7 /* SIGTERM. */
+#define IPO_STRING 8 /* Input string: IPO_STR. */
+#define IPO_WRITE 9 /* Write. */
+
+/*
+ * IP events sent from vi to the screen.
+ */
+#define IPO_ADDSTR 1 /* Add a string: IPO_STR. */
+#define IPO_ATTRIBUTE 2 /* Set screen attribute: IPO_INT, IPO_INT. */
+#define IPO_BELL 3 /* Beep/bell/flash the terminal. */
+#define IPO_BUSY 4 /* Display a busy message: IPO_STR. */
+#define IPO_CLRTOEOL 5 /* Clear to the end of the line. */
+#define IPO_DELETELN 6 /* Delete a line. */
+#define IPO_INSERTLN 7 /* Insert a line. */
+#define IPO_MOVE 8 /* Move the cursor: IPO_INT, IPO_INT. */
+#define IPO_REDRAW 9 /* Redraw the screen. */
+#define IPO_REFRESH 10 /* Refresh the screen. */
+#define IPO_RENAME 11 /* Rename the screen: IPO_STR. */
+#define IPO_REWRITE 12 /* Rewrite a line: IPO_INT. */
+
+#include "ip_extern.h"
diff --git a/contrib/nvi/ip/ip_funcs.c b/contrib/nvi/ip/ip_funcs.c
new file mode 100644
index 0000000..c92f1ed
--- /dev/null
+++ b/contrib/nvi/ip/ip_funcs.c
@@ -0,0 +1,443 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ip_funcs.c 8.4 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+#include "ip.h"
+
+static int ip_send __P((SCR *, char *, IP_BUF *));
+
+/*
+ * ip_addstr --
+ * Add len bytes from the string at the cursor, advancing the cursor.
+ *
+ * PUBLIC: int ip_addstr __P((SCR *, const char *, size_t));
+ */
+int
+ip_addstr(sp, str, len)
+ SCR *sp;
+ const char *str;
+ size_t len;
+{
+ IP_BUF ipb;
+ IP_PRIVATE *ipp;
+ int iv, rval;
+
+ ipp = IPP(sp);
+
+ /*
+ * If ex isn't in control, it's the last line of the screen and
+ * it's a split screen, use inverse video.
+ */
+ iv = 0;
+ if (!F_ISSET(sp, SC_SCR_EXWROTE) &&
+ ipp->row == LASTLINE(sp) && IS_SPLIT(sp)) {
+ iv = 1;
+ ip_attr(sp, SA_INVERSE, 1);
+ }
+ ipb.code = IPO_ADDSTR;
+ ipb.len = len;
+ ipb.str = str;
+ rval = ip_send(sp, "s", &ipb);
+
+ if (iv)
+ ip_attr(sp, SA_INVERSE, 0);
+ return (rval);
+}
+
+/*
+ * ip_attr --
+ * Toggle a screen attribute on/off.
+ *
+ * PUBLIC: int ip_attr __P((SCR *, scr_attr_t, int));
+ */
+int
+ip_attr(sp, attribute, on)
+ SCR *sp;
+ scr_attr_t attribute;
+ int on;
+{
+ IP_BUF ipb;
+
+ ipb.code = IPO_ATTRIBUTE;
+ ipb.val1 = attribute;
+ ipb.val2 = on;
+
+ return (ip_send(sp, "12", &ipb));
+}
+
+/*
+ * ip_baud --
+ * Return the baud rate.
+ *
+ * PUBLIC: int ip_baud __P((SCR *, u_long *));
+ */
+int
+ip_baud(sp, ratep)
+ SCR *sp;
+ u_long *ratep;
+{
+ *ratep = 9600; /* XXX: Translation: fast. */
+ return (0);
+}
+
+/*
+ * ip_bell --
+ * Ring the bell/flash the screen.
+ *
+ * PUBLIC: int ip_bell __P((SCR *));
+ */
+int
+ip_bell(sp)
+ SCR *sp;
+{
+ IP_BUF ipb;
+
+ ipb.code = IPO_BELL;
+
+ return (ip_send(sp, NULL, &ipb));
+}
+
+/*
+ * ip_busy --
+ * Display a busy message.
+ *
+ * PUBLIC: void ip_busy __P((SCR *, const char *, busy_t));
+ */
+void
+ip_busy(sp, str, bval)
+ SCR *sp;
+ const char *str;
+ busy_t bval;
+{
+ IP_BUF ipb;
+
+ ipb.code = IPO_BUSY;
+ if (str == NULL) {
+ ipb.len = 0;
+ ipb.str = "";
+ } else {
+ ipb.len = strlen(str);
+ ipb.str = str;
+ }
+ ipb.val1 = bval;
+
+ (void)ip_send(sp, "s1", &ipb);
+}
+
+/*
+ * ip_clrtoeol --
+ * Clear from the current cursor to the end of the line.
+ *
+ * PUBLIC: int ip_clrtoeol __P((SCR *));
+ */
+int
+ip_clrtoeol(sp)
+ SCR *sp;
+{
+ IP_BUF ipb;
+
+ ipb.code = IPO_CLRTOEOL;
+
+ return (ip_send(sp, NULL, &ipb));
+}
+
+/*
+ * ip_cursor --
+ * Return the current cursor position.
+ *
+ * PUBLIC: int ip_cursor __P((SCR *, size_t *, size_t *));
+ */
+int
+ip_cursor(sp, yp, xp)
+ SCR *sp;
+ size_t *yp, *xp;
+{
+ IP_PRIVATE *ipp;
+
+ ipp = IPP(sp);
+ *yp = ipp->row;
+ *xp = ipp->col;
+ return (0);
+}
+
+/*
+ * ip_deleteln --
+ * Delete the current line, scrolling all lines below it.
+ *
+ * PUBLIC: int ip_deleteln __P((SCR *));
+ */
+int
+ip_deleteln(sp)
+ SCR *sp;
+{
+ IP_BUF ipb;
+
+ /*
+ * This clause is required because the curses screen uses reverse
+ * video to delimit split screens. If the screen does not do this,
+ * this code won't be necessary.
+ *
+ * If the bottom line was in reverse video, rewrite it in normal
+ * video before it's scrolled.
+ */
+ if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) {
+ ipb.code = IPO_REWRITE;
+ ipb.val1 = RLNO(sp, LASTLINE(sp));
+ if (ip_send(sp, "1", &ipb))
+ return (1);
+ }
+
+ /*
+ * The bottom line is expected to be blank after this operation,
+ * and other screens must support that semantic.
+ */
+ ipb.code = IPO_DELETELN;
+ return (ip_send(sp, NULL, &ipb));
+}
+
+/*
+ * ip_ex_adjust --
+ * Adjust the screen for ex.
+ *
+ * PUBLIC: int ip_ex_adjust __P((SCR *, exadj_t));
+ */
+int
+ip_ex_adjust(sp, action)
+ SCR *sp;
+ exadj_t action;
+{
+ abort();
+ /* NOTREACHED */
+}
+
+/*
+ * ip_insertln --
+ * Push down the current line, discarding the bottom line.
+ *
+ * PUBLIC: int ip_insertln __P((SCR *));
+ */
+int
+ip_insertln(sp)
+ SCR *sp;
+{
+ IP_BUF ipb;
+
+ ipb.code = IPO_INSERTLN;
+
+ return (ip_send(sp, NULL, &ipb));
+}
+
+/*
+ * ip_keyval --
+ * Return the value for a special key.
+ *
+ * PUBLIC: int ip_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+ */
+int
+ip_keyval(sp, val, chp, dnep)
+ SCR *sp;
+ scr_keyval_t val;
+ CHAR_T *chp;
+ int *dnep;
+{
+ /*
+ * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990,
+ * VWERASE is a 4BSD extension.
+ */
+ switch (val) {
+ case KEY_VEOF:
+ *dnep = '\004'; /* ^D */
+ break;
+ case KEY_VERASE:
+ *dnep = '\b'; /* ^H */
+ break;
+ case KEY_VKILL:
+ *dnep = '\025'; /* ^U */
+ break;
+#ifdef VWERASE
+ case KEY_VWERASE:
+ *dnep = '\027'; /* ^W */
+ break;
+#endif
+ default:
+ *dnep = 1;
+ break;
+ }
+ return (0);
+}
+
+/*
+ * ip_move --
+ * Move the cursor.
+ *
+ * PUBLIC: int ip_move __P((SCR *, size_t, size_t));
+ */
+int
+ip_move(sp, lno, cno)
+ SCR *sp;
+ size_t lno, cno;
+{
+ IP_PRIVATE *ipp;
+ IP_BUF ipb;
+
+ ipp = IPP(sp);
+ ipp->row = lno;
+ ipp->col = cno;
+
+ ipb.code = IPO_MOVE;
+ ipb.val1 = RLNO(sp, lno);
+ ipb.val2 = cno;
+ return (ip_send(sp, "12", &ipb));
+}
+
+/*
+ * ip_refresh --
+ * Refresh the screen.
+ *
+ * PUBLIC: int ip_refresh __P((SCR *, int));
+ */
+int
+ip_refresh(sp, repaint)
+ SCR *sp;
+ int repaint;
+{
+ IP_BUF ipb;
+
+ ipb.code = repaint ? IPO_REDRAW : IPO_REFRESH;
+
+ return (ip_send(sp, NULL, &ipb));
+}
+
+/*
+ * ip_rename --
+ * Rename the file.
+ *
+ * PUBLIC: int ip_rename __P((SCR *));
+ */
+int
+ip_rename(sp)
+ SCR *sp;
+{
+ IP_BUF ipb;
+
+ ipb.code = IPO_RENAME;
+ ipb.len = strlen(sp->frp->name);
+ ipb.str = sp->frp->name;
+
+ return (ip_send(sp, "s", &ipb));
+}
+
+/*
+ * ip_suspend --
+ * Suspend a screen.
+ *
+ * PUBLIC: int ip_suspend __P((SCR *, int *));
+ */
+int
+ip_suspend(sp, allowedp)
+ SCR *sp;
+ int *allowedp;
+{
+ *allowedp = 0;
+ return (0);
+}
+
+/*
+ * ip_usage --
+ * Print out the ip usage messages.
+ *
+ * PUBLIC: void ip_usage __P((void));
+ */
+void
+ip_usage()
+{
+#define USAGE "\
+usage: vi [-eFlRrSv] [-c command] [-I ifd.ofd] [-t tag] [-w size] [file ...]\n"
+ (void)fprintf(stderr, "%s", USAGE);
+#undef USAGE
+}
+
+/*
+ * ip_send --
+ * Construct and send an IP buffer.
+ */
+static int
+ip_send(sp, fmt, ipbp)
+ SCR *sp;
+ char *fmt;
+ IP_BUF *ipbp;
+{
+ IP_PRIVATE *ipp;
+ size_t blen, off;
+ u_int32_t ilen;
+ int nlen, n, nw, rval;
+ char *bp, *p;
+
+ ipp = IPP(sp);
+
+ GET_SPACE_RET(sp, bp, blen, 128);
+
+ p = bp;
+ nlen = 0;
+ *p++ = ipbp->code;
+ nlen += IPO_CODE_LEN;
+
+ if (fmt != NULL)
+ for (; *fmt != '\0'; ++fmt)
+ switch (*fmt) {
+ case '1': /* Value 1. */
+ ilen = htonl(ipbp->val1);
+ goto value;
+ case '2': /* Value 2. */
+ ilen = htonl(ipbp->val2);
+value: nlen += IPO_INT_LEN;
+ off = p - bp;
+ ADD_SPACE_RET(sp, bp, blen, nlen);
+ p = bp + off;
+ memmove(p, &ilen, IPO_INT_LEN);
+ p += IPO_INT_LEN;
+ break;
+ case 's': /* String. */
+ ilen = ipbp->len; /* XXX: conversion. */
+ ilen = htonl(ilen);
+ nlen += IPO_INT_LEN + ipbp->len;
+ off = p - bp;
+ ADD_SPACE_RET(sp, bp, blen, nlen);
+ p = bp + off;
+ memmove(p, &ilen, IPO_INT_LEN);
+ p += IPO_INT_LEN;
+ memmove(p, ipbp->str, ipbp->len);
+ p += ipbp->len;
+ break;
+ }
+
+
+ rval = 0;
+ for (n = p - bp, p = bp; n > 0; n -= nw, p += nw)
+ if ((nw = write(ipp->o_fd, p, n)) < 0) {
+ rval = 1;
+ break;
+ }
+
+ FREE_SPACE(sp, bp, blen);
+
+ return (rval);
+}
diff --git a/contrib/nvi/ip/ip_main.c b/contrib/nvi/ip/ip_main.c
new file mode 100644
index 0000000..7ca9f55
--- /dev/null
+++ b/contrib/nvi/ip/ip_main.c
@@ -0,0 +1,165 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ip_main.c 8.3 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "ip.h"
+
+static void ip_func_std __P((GS *));
+static IP_PRIVATE *ip_init __P((GS *, char *));
+static void perr __P((char *, char *));
+
+/*
+ * main --
+ * This is the main loop for the vi-as-library editor.
+ */
+int
+ip_main(argc, argv, gp, ip_arg)
+ int argc;
+ char *argv[], *ip_arg;
+ GS *gp;
+{
+ EVENT ev;
+ IP_PRIVATE *ipp;
+ IP_BUF ipb;
+ int rval;
+
+ /* Create and partially initialize the IP structure. */
+ if ((ipp = ip_init(gp, ip_arg)) == NULL)
+ return (1);
+
+ /* Add the terminal type to the global structure. */
+ if ((OG_D_STR(gp, GO_TERM) =
+ OG_STR(gp, GO_TERM) = strdup("ip_curses")) == NULL)
+ perr(gp->progname, NULL);
+
+ /*
+ * Figure out how big the screen is -- read events until we get
+ * the rows and columns.
+ */
+ do {
+ if (ip_event(NULL, &ev, 0, 0))
+ return (1);
+ } while (ev.e_event != E_EOF && ev.e_event != E_ERR &&
+ ev.e_event != E_QUIT && ev.e_event != E_WRESIZE &&
+ ev.e_event != E_SIGHUP && ev.e_event != E_SIGTERM);
+ if (ev.e_event != E_WRESIZE)
+ return (1);
+
+ /* Run ex/vi. */
+ rval = editor(gp, argc, argv);
+
+ /* Clean up the screen. */
+ (void)ip_quit(gp);
+
+ /* Free the global and IP private areas. */
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+ free(ipp);
+ free(gp);
+#endif
+
+ return (rval);
+}
+
+/*
+ * ip_init --
+ * Create and partially initialize the GS structure.
+ */
+static IP_PRIVATE *
+ip_init(gp, ip_arg)
+ GS *gp;
+ char *ip_arg;
+{
+ IP_PRIVATE *ipp;
+ char *ep;
+
+ /* Allocate the IP private structure. */
+ CALLOC_NOMSG(NULL, ipp, IP_PRIVATE *, 1, sizeof(IP_PRIVATE));
+ if (ipp == NULL)
+ perr(gp->progname, NULL);
+ gp->ip_private = ipp;
+
+ /*
+ * Crack ip_arg -- it's of the form #.#, where the first number is the
+ * file descriptor from the screen, the second is the file descriptor
+ * to the screen.
+ */
+ if (!isdigit(ip_arg[0]))
+ goto usage;
+ ipp->i_fd = strtol(ip_arg, &ep, 10);
+ if (ep[0] != '.' || !isdigit(ep[1]))
+ goto usage;
+ ipp->o_fd = strtol(++ep, &ep, 10);
+ if (ep[0] != '\0') {
+usage: ip_usage();
+ return (NULL);
+ }
+
+ /* Initialize the list of ip functions. */
+ ip_func_std(gp);
+
+ return (ipp);
+}
+
+/*
+ * ip_func_std --
+ * Initialize the standard ip functions.
+ */
+static void
+ip_func_std(gp)
+ GS *gp;
+{
+ gp->scr_addstr = ip_addstr;
+ gp->scr_attr = ip_attr;
+ gp->scr_baud = ip_baud;
+ gp->scr_bell = ip_bell;
+ gp->scr_busy = ip_busy;
+ gp->scr_clrtoeol = ip_clrtoeol;
+ gp->scr_cursor = ip_cursor;
+ gp->scr_deleteln = ip_deleteln;
+ gp->scr_event = ip_event;
+ gp->scr_ex_adjust = ip_ex_adjust;
+ gp->scr_fmap = ip_fmap;
+ gp->scr_insertln = ip_insertln;
+ gp->scr_keyval = ip_keyval;
+ gp->scr_move = ip_move;
+ gp->scr_msg = NULL;
+ gp->scr_optchange = ip_optchange;
+ gp->scr_refresh = ip_refresh;
+ gp->scr_rename = ip_rename;
+ gp->scr_screen = ip_screen;
+ gp->scr_suspend = ip_suspend;
+ gp->scr_usage = ip_usage;
+}
+
+/*
+ * perr --
+ * Print system error.
+ */
+static void
+perr(name, msg)
+ char *name, *msg;
+{
+ (void)fprintf(stderr, "%s:", name);
+ if (msg != NULL)
+ (void)fprintf(stderr, "%s:", msg);
+ (void)fprintf(stderr, "%s\n", strerror(errno));
+ exit(1);
+}
diff --git a/contrib/nvi/ip/ip_read.c b/contrib/nvi/ip/ip_read.c
new file mode 100644
index 0000000..9fd9777
--- /dev/null
+++ b/contrib/nvi/ip/ip_read.c
@@ -0,0 +1,307 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ip_read.c 8.3 (Berkeley) 9/24/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <termios.h>
+#include <time.h>
+
+#include "../common/common.h"
+#include "../ex/script.h"
+#include "ip.h"
+
+extern GS *__global_list;
+
+typedef enum { INP_OK=0, INP_EOF, INP_ERR, INP_TIMEOUT } input_t;
+
+static input_t ip_read __P((SCR *, IP_PRIVATE *, struct timeval *));
+static int ip_resize __P((SCR *, size_t, size_t));
+static int ip_trans __P((SCR *, IP_PRIVATE *, EVENT *));
+
+/*
+ * ip_event --
+ * Return a single event.
+ *
+ * PUBLIC: int ip_event __P((SCR *, EVENT *, u_int32_t, int));
+ */
+int
+ip_event(sp, evp, flags, ms)
+ SCR *sp;
+ EVENT *evp;
+ u_int32_t flags;
+ int ms;
+{
+ IP_PRIVATE *ipp;
+ struct timeval t, *tp;
+
+ if (LF_ISSET(EC_INTERRUPT)) { /* XXX */
+ evp->e_event = E_TIMEOUT;
+ return (0);
+ }
+
+ ipp = sp == NULL ? GIPP(__global_list) : IPP(sp);
+
+ /* Discard the last command. */
+ if (ipp->iskip != 0) {
+ ipp->iblen -= ipp->iskip;
+ memmove(ipp->ibuf, ipp->ibuf + ipp->iskip, ipp->iblen);
+ ipp->iskip = 0;
+ }
+
+ /* Set timer. */
+ if (ms == 0)
+ tp = NULL;
+ else {
+ t.tv_sec = ms / 1000;
+ t.tv_usec = (ms % 1000) * 1000;
+ tp = &t;
+ }
+
+ /* Read input events. */
+ for (;;) {
+ switch (ip_read(sp, ipp, tp)) {
+ case INP_OK:
+ if (!ip_trans(sp, ipp, evp))
+ continue;
+ break;
+ case INP_EOF:
+ evp->e_event = E_EOF;
+ break;
+ case INP_ERR:
+ evp->e_event = E_ERR;
+ break;
+ case INP_TIMEOUT:
+ evp->e_event = E_TIMEOUT;
+ break;
+ default:
+ abort();
+ }
+ break;
+ }
+ return (0);
+}
+
+/*
+ * ip_read --
+ * Read characters from the input.
+ */
+static input_t
+ip_read(sp, ipp, tp)
+ SCR *sp;
+ IP_PRIVATE *ipp;
+ struct timeval *tp;
+{
+ struct timeval poll;
+ GS *gp;
+ SCR *tsp;
+ fd_set rdfd;
+ input_t rval;
+ size_t blen;
+ int maxfd, nr;
+ char *bp;
+
+ gp = sp == NULL ? __global_list : sp->gp;
+ bp = ipp->ibuf + ipp->iblen;
+ blen = sizeof(ipp->ibuf) - ipp->iblen;
+
+ /*
+ * 1: A read with an associated timeout, e.g., trying to complete
+ * a map sequence. If input exists, we fall into #2.
+ */
+ FD_ZERO(&rdfd);
+ poll.tv_sec = 0;
+ poll.tv_usec = 0;
+ if (tp != NULL) {
+ FD_SET(ipp->i_fd, &rdfd);
+ switch (select(ipp->i_fd + 1,
+ &rdfd, NULL, NULL, tp == NULL ? &poll : tp)) {
+ case 0:
+ return (INP_TIMEOUT);
+ case -1:
+ goto err;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * 2: Wait for input.
+ *
+ * Select on the command input and scripting window file descriptors.
+ * It's ugly that we wait on scripting file descriptors here, but it's
+ * the only way to keep from locking out scripting windows.
+ */
+ if (sp != NULL && F_ISSET(gp, G_SCRWIN)) {
+loop: FD_ZERO(&rdfd);
+ FD_SET(ipp->i_fd, &rdfd);
+ maxfd = ipp->i_fd;
+ for (tsp = gp->dq.cqh_first;
+ tsp != (void *)&gp->dq; tsp = tsp->q.cqe_next)
+ if (F_ISSET(sp, SC_SCRIPT)) {
+ FD_SET(sp->script->sh_master, &rdfd);
+ if (sp->script->sh_master > maxfd)
+ maxfd = sp->script->sh_master;
+ }
+ switch (select(maxfd + 1, &rdfd, NULL, NULL, NULL)) {
+ case 0:
+ abort();
+ case -1:
+ goto err;
+ default:
+ break;
+ }
+ if (!FD_ISSET(ipp->i_fd, &rdfd)) {
+ if (sscr_input(sp))
+ return (INP_ERR);
+ goto loop;
+ }
+ }
+
+ /*
+ * 3: Read the input.
+ */
+ switch (nr = read(ipp->i_fd, bp, blen)) {
+ case 0: /* EOF. */
+ rval = INP_EOF;
+ break;
+ case -1: /* Error or interrupt. */
+err: rval = INP_ERR;
+ msgq(sp, M_SYSERR, "input");
+ break;
+ default: /* Input characters. */
+ ipp->iblen += nr;
+ rval = INP_OK;
+ break;
+ }
+ return (rval);
+}
+
+/*
+ * ip_trans --
+ * Translate messages into events.
+ */
+static int
+ip_trans(sp, ipp, evp)
+ SCR *sp;
+ IP_PRIVATE *ipp;
+ EVENT *evp;
+{
+ u_int32_t val1, val2;
+
+ switch (ipp->ibuf[0]) {
+ case IPO_EOF:
+ evp->e_event = E_EOF;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ case IPO_ERR:
+ evp->e_event = E_ERR;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ case IPO_INTERRUPT:
+ evp->e_event = E_INTERRUPT;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ case IPO_QUIT:
+ evp->e_event = E_QUIT;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ case IPO_RESIZE:
+ if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN * 2)
+ return (0);
+ evp->e_event = E_WRESIZE;
+ memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN);
+ val1 = ntohl(val1);
+ memcpy(&val2,
+ ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN, IPO_INT_LEN);
+ val2 = ntohl(val2);
+ ip_resize(sp, val1, val2);
+ ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN * 2;
+ return (1);
+ case IPO_SIGHUP:
+ evp->e_event = E_SIGHUP;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ case IPO_SIGTERM:
+ evp->e_event = E_SIGTERM;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ case IPO_STRING:
+ evp->e_event = E_STRING;
+string: if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN)
+ return (0);
+ memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN);
+ val1 = ntohl(val1);
+ if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN + val1)
+ return (0);
+ ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN + val1;
+ evp->e_csp = ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN;
+ evp->e_len = val1;
+ return (1);
+ case IPO_WRITE:
+ evp->e_event = E_WRITE;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ default:
+ /*
+ * XXX: Protocol is out of sync?
+ */
+ abort();
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * ip_resize --
+ * Reset the options for a resize event.
+ */
+static int
+ip_resize(sp, lines, columns)
+ SCR *sp;
+ size_t lines, columns;
+{
+ GS *gp;
+ ARGS *argv[2], a, b;
+ char b1[1024];
+
+ /*
+ * XXX
+ * The IP screen has to know the lines and columns before anything
+ * else happens. So, we may not have a valid SCR pointer, and we
+ * have to deal with that.
+ */
+ if (sp == NULL) {
+ gp = __global_list;
+ OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = lines;
+ OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = columns;
+ return (0);
+ }
+
+ a.bp = b1;
+ b.bp = NULL;
+ a.len = b.len = 0;
+ argv[0] = &a;
+ argv[1] = &b;
+
+ (void)snprintf(b1, sizeof(b1), "lines=%lu", (u_long)lines);
+ a.len = strlen(b1);
+ if (opts_set(sp, argv, NULL))
+ return (1);
+ (void)snprintf(b1, sizeof(b1), "columns=%lu", (u_long)columns);
+ a.len = strlen(b1);
+ if (opts_set(sp, argv, NULL))
+ return (1);
+ return (0);
+}
diff --git a/contrib/nvi/ip/ip_screen.c b/contrib/nvi/ip/ip_screen.c
new file mode 100644
index 0000000..71578e0
--- /dev/null
+++ b/contrib/nvi/ip/ip_screen.c
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ip_screen.c 8.2 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "ip.h"
+
+/*
+ * ip_screen --
+ * Initialize/shutdown the IP screen.
+ *
+ * PUBLIC: int ip_screen __P((SCR *, u_int32_t));
+ */
+int
+ip_screen(sp, flags)
+ SCR *sp;
+ u_int32_t flags;
+{
+ GS *gp;
+ IP_PRIVATE *ipp;
+
+ gp = sp->gp;
+ ipp = IPP(sp);
+
+ /* See if the current information is incorrect. */
+ if (F_ISSET(gp, G_SRESTART)) {
+ if (ip_quit(gp))
+ return (1);
+ F_CLR(gp, G_SRESTART);
+ }
+
+ /* See if we're already in the right mode. */
+ if (LF_ISSET(SC_VI) && F_ISSET(ipp, IP_SCR_VI_INIT))
+ return (0);
+
+ /* Ex isn't possible. */
+ if (LF_ISSET(SC_EX))
+ return (1);
+
+ /* Initialize terminal based information. */
+ if (ip_term_init(sp))
+ return (1);
+
+ /* Put up the first file name. */
+ if (ip_rename(sp))
+ return (1);
+
+ F_SET(ipp, IP_SCR_VI_INIT);
+ return (0);
+}
+
+/*
+ * ip_quit --
+ * Shutdown the screens.
+ *
+ * PUBLIC: int ip_quit __P((GS *));
+ */
+int
+ip_quit(gp)
+ GS *gp;
+{
+ IP_PRIVATE *ipp;
+ int rval;
+
+ /* Clean up the terminal mappings. */
+ rval = ip_term_end(gp);
+
+ ipp = GIPP(gp);
+ F_CLR(ipp, IP_SCR_VI_INIT);
+
+ return (rval);
+}
diff --git a/contrib/nvi/ip/ip_term.c b/contrib/nvi/ip/ip_term.c
new file mode 100644
index 0000000..28e686d
--- /dev/null
+++ b/contrib/nvi/ip/ip_term.c
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ip_term.c 8.2 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "ip.h"
+
+/*
+ * ip_term_init --
+ * Initialize the terminal special keys.
+ *
+ * PUBLIC: int ip_term_init __P((SCR *));
+ */
+int
+ip_term_init(sp)
+ SCR *sp;
+{
+ SEQ *qp;
+
+ /*
+ * Rework any function key mappings that were set before the
+ * screen was initialized.
+ */
+ for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next)
+ if (F_ISSET(qp, SEQ_FUNCMAP))
+ (void)ip_fmap(sp, qp->stype,
+ qp->input, qp->ilen, qp->output, qp->olen);
+ return (0);
+}
+
+/*
+ * ip_term_end --
+ * End the special keys defined by the termcap/terminfo entry.
+ *
+ * PUBLIC: int ip_term_end __P((GS *));
+ */
+int
+ip_term_end(gp)
+ GS *gp;
+{
+ SEQ *qp, *nqp;
+
+ /* Delete screen specific mappings. */
+ for (qp = gp->seqq.lh_first; qp != NULL; qp = nqp) {
+ nqp = qp->q.le_next;
+ if (F_ISSET(qp, SEQ_SCREEN))
+ (void)seq_mdel(qp);
+ }
+ return (0);
+}
+
+/*
+ * ip_fmap --
+ * Map a function key.
+ *
+ * PUBLIC: int ip_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+ */
+int
+ip_fmap(sp, stype, from, flen, to, tlen)
+ SCR *sp;
+ seq_t stype;
+ CHAR_T *from, *to;
+ size_t flen, tlen;
+{
+ /* Bind a function key to a string sequence. */
+ return (1);
+}
+
+/*
+ * ip_optchange --
+ * IP screen specific "option changed" routine.
+ *
+ * PUBLIC: int ip_optchange __P((SCR *, int, char *, u_long *));
+ */
+int
+ip_optchange(sp, opt, str, valp)
+ SCR *sp;
+ int opt;
+ char *str;
+ u_long *valp;
+{
+ switch (opt) {
+ case O_COLUMNS:
+ case O_LINES:
+ F_SET(sp->gp, G_SRESTART);
+ F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
+ break;
+ case O_TERM:
+ msgq(sp, M_ERR, "The screen type may not be changed");
+ return (1);
+ }
+ return (0);
+}
OpenPOWER on IntegriCloud