diff options
Diffstat (limited to 'contrib/nvi/ip')
-rw-r--r-- | contrib/nvi/ip/IP_INSTRUCTIONS | 41 | ||||
-rw-r--r-- | contrib/nvi/ip/ip.h | 92 | ||||
-rw-r--r-- | contrib/nvi/ip/ip_funcs.c | 443 | ||||
-rw-r--r-- | contrib/nvi/ip/ip_main.c | 165 | ||||
-rw-r--r-- | contrib/nvi/ip/ip_read.c | 307 | ||||
-rw-r--r-- | contrib/nvi/ip/ip_screen.c | 87 | ||||
-rw-r--r-- | contrib/nvi/ip/ip_term.c | 108 |
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); +} |