Path: seismo!harvard!talcott!panda!Paul Placeway From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: Termcap support for MicroEmacs v. 30 sources Message-ID: <1746@panda.UUCP> Date: 25 Apr 86 13:04:35 GMT Sender: jpn@panda.UUCP Lines: 915 Approved: jpn@panda.UUCP Mod.sources: Volume 4, Issue 79 Submitted by: Paul Placeway These are the changes for VERSION 30 MicroEmacs to do Unix termcap support. They have been tested under 4.2 BSD Unix, and should work under 4.1, and 4.3. Changes for any USG version will take more work (i.e. extensive changes to sys/ultrix/* and tty/termcap/*). Installition instructions for MicroEmacs version 30 termcap support: 1) Go to the directory containing the MicroEmacs version 30 distribution (version 30 is the one posted to mod.sources) 2) unshar the following shar file (trim at the ---cut here-- and run through sh). 3) apply the ./sys/ultrix/ttyio.diff diffs to ttyio.c (by hand or by the patch program). 4) copy Makefile.tc to Makefile 5) edit the Makefile a bit if you like 6) make. You MUST either use the Makefile supplied, or re-edit the ultrix Makefile so that the tty is termcap and it does a -ltermcap on the link step. If you have any problems, send me mail and I will try to figure things out. -- Paul Placeway paul@ohio-state ...!cbosgd!osu-eddie!paul -----------------cut here------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # Makefile.tc # sys/ultrix/ttyio.diff # tty/termcap/tty.c # tty/termcap/ttydef.h # tty/termcap/ttykbd.c # This archive created: Fri Apr 25 07:59:50 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'Makefile.tc'" '(1064 characters)' if test -f 'Makefile.tc' then echo shar: will not over-write existing file "'Makefile.tc'" else cat << \SHAR_EOF > 'Makefile.tc' # Makefile for MicroEMACS. # Is there a better way to do the rebuilds, other than using # the links? SYS = ultrix TTY = termcap LIBS = -ltermcap CFLAGS = -O DEST = /u/paul/bin/m OBJ = basic.o \ buffer.o \ cinfo.o \ display.o \ echo.o \ extend.o \ file.o \ kbd.o \ line.o \ main.o \ random.o \ region.o \ search.o \ symbol.o \ version.o \ window.o \ word.o \ fileio.o \ spawn.o \ ttyio.o \ tty.o \ ttykbd.o xemacs: $(OBJ) cc -o xemacs $(OBJ) $(LIBS) $(OBJ): def.h sysdef.h ttydef.h sysdef.h: sys/$(SYS)/sysdef.h # Update links, if needed. rm -f sysdef.h ln sys/$(SYS)/sysdef.h . ttydef.h: tty/$(TTY)/ttydef.h rm -f ttydef.h ln tty/$(TTY)/ttydef.h . fileio.c: sys/$(SYS)/fileio.c rm -f fileio.c ln sys/$(SYS)/fileio.c . spawn.c: sys/$(SYS)/spawn.c rm -f spawn.c ln sys/$(SYS)/spawn.c . tty.c: tty/$(TTY)/tty.c rm -f tty.c ln tty/$(TTY)/tty.c . ttyio.c: sys/$(SYS)/ttyio.c rm -f ttyio.c ln sys/$(SYS)/ttyio.c . ttykbd.c: tty/$(TTY)/ttykbd.c rm -f ttykbd.c ln tty/$(TTY)/ttykbd.c . install: xemacs cp xemacs $(DEST) SHAR_EOF if test 1064 -ne "`wc -c < 'Makefile.tc'`" then echo shar: error transmitting "'Makefile.tc'" '(should have been 1064 characters)' fi fi if test ! -d 'sys' then echo shar: creating directory "'sys'" mkdir 'sys' fi if test ! -d 'sys/ultrix' then echo shar: creating directory "'sys/ultrix'" mkdir 'sys/ultrix' fi echo shar: extracting "'sys/ultrix/ttyio.diff'" '(4313 characters)' if test -f 'sys/ultrix/ttyio.diff' then echo shar: will not over-write existing file "'sys/ultrix/ttyio.diff'" else cat << \SHAR_EOF > 'sys/ultrix/ttyio.diff' *** ttyio.old Tue Apr 22 17:24:48 1986 --- ttyio.c Tue Apr 22 18:11:39 1986 *************** *** 1,10 /* * Name: MicroEMACS ! * Ultrix-32 terminal I/O. ! * Version: 29 ! * Last edit: 05-Feb-86 ! * By: rex::conroy ! * decvax!decwrl!dec-rhea!dec-rex!conroy * * The functions in this file * negotiate with the operating system for --- 1,10 ----- /* * Name: MicroEMACS ! * Ultrix-32 and Unix terminal I/O. ! * Version: 29 -- osu 2 ! * Last edit: 22-Apr-86 ! * By: paul@ohio-state ! * cbosgd!osu-eddie!paul * * The functions in this file * negotiate with the operating system for *************** *** 38,44 ttopen() { register char *cp; ! extern char *getenv(); if (ioctl(0, TIOCGETP, &oldtty) < 0) abort(); --- 38,48 ----- ttopen() { register char *cp; ! char *getenv(); ! char *t, *p, *tgetstr(); ! char tcbuf[1024]; ! char *tv_stype; ! char err_str[72]; if (ioctl(0, TIOCGETP, &oldtty) < 0) abort(); *************** *** 48,53 newtty.sg_kill = oldtty.sg_kill; newtty.sg_flags = oldtty.sg_flags; newtty.sg_flags &= ~(ECHO|CRMOD); /* Kill echo, CR=>NL. */ newtty.sg_flags |= CBREAK; /* Half-cooked mode. */ if (ioctl(0, TIOCSETP, &newtty) < 0) abort(); --- 52,58 ----- newtty.sg_kill = oldtty.sg_kill; newtty.sg_flags = oldtty.sg_flags; newtty.sg_flags &= ~(ECHO|CRMOD); /* Kill echo, CR=>NL. */ + #if FLOWCONTROL newtty.sg_flags |= CBREAK; /* Half-cooked mode. */ #else newtty.sg_flags |= RAW|ANYP; /* raw mode for 8 bit path.*/ *************** *** 49,54 newtty.sg_flags = oldtty.sg_flags; newtty.sg_flags &= ~(ECHO|CRMOD); /* Kill echo, CR=>NL. */ newtty.sg_flags |= CBREAK; /* Half-cooked mode. */ if (ioctl(0, TIOCSETP, &newtty) < 0) abort(); if (ioctl(0, TIOCGETC, &oldtchars) < 0) --- 54,62 ----- newtty.sg_flags &= ~(ECHO|CRMOD); /* Kill echo, CR=>NL. */ #if FLOWCONTROL newtty.sg_flags |= CBREAK; /* Half-cooked mode. */ + #else + newtty.sg_flags |= RAW|ANYP; /* raw mode for 8 bit path.*/ + #endif if (ioctl(0, TIOCSETP, &newtty) < 0) abort(); if (ioctl(0, TIOCGETC, &oldtchars) < 0) *************** *** 55,60 abort(); newtchars.t_intrc = 0xFF; /* Interrupt. */ newtchars.t_quitc = 0xFF; /* Quit. */ newtchars.t_startc = 0x11; /* ^Q, for terminal. */ newtchars.t_stopc = 0x13; /* ^S, for terminal. */ newtchars.t_eofc = 0xFF; --- 63,69 ----- abort(); newtchars.t_intrc = 0xFF; /* Interrupt. */ newtchars.t_quitc = 0xFF; /* Quit. */ + #if FLOWCONTROL newtchars.t_startc = 0x11; /* ^Q, for terminal. */ newtchars.t_stopc = 0x13; /* ^S, for terminal. */ #else *************** *** 57,62 newtchars.t_quitc = 0xFF; /* Quit. */ newtchars.t_startc = 0x11; /* ^Q, for terminal. */ newtchars.t_stopc = 0x13; /* ^S, for terminal. */ newtchars.t_eofc = 0xFF; newtchars.t_brkc = 0xFF; if (ioctl(0, TIOCSETC, &newtchars) < 0) --- 66,75 ----- #if FLOWCONTROL newtchars.t_startc = 0x11; /* ^Q, for terminal. */ newtchars.t_stopc = 0x13; /* ^S, for terminal. */ + #else + newtchars.t_startc = 0xFF; /* ^Q, for terminal. */ + newtchars.t_stopc = 0xFF; /* ^S, for terminal. */ + #endif newtchars.t_eofc = 0xFF; newtchars.t_brkc = 0xFF; if (ioctl(0, TIOCSETC, &newtchars) < 0) *************** *** 71,79 newltchars.t_lnextc = 0xFF; /* Literal next. */ if (ioctl(0, TIOCSLTC, &newltchars) < 0) abort(); ! if ((cp=getenv("TERMCAP")) == NULL ! || (nrow=getvalue(cp, "li")) <= 0 ! || (ncol=getvalue(cp, "co")) <= 0) { nrow = 24; ncol = 80; } --- 84,106 ----- newltchars.t_lnextc = 0xFF; /* Literal next. */ if (ioctl(0, TIOCSLTC, &newltchars) < 0) abort(); ! ! /* do this the REAL way */ ! if ((tv_stype = getenv("TERM")) == NULL) ! { ! puts("Environment variable TERM not defined!"); ! exit(1); ! } ! ! if((tgetent(tcbuf, tv_stype)) != 1) ! { ! sprintf(err_str, "Unknown terminal type %s!", tv_stype); ! puts(err_str); ! exit(1); ! } ! ! if ((nrow=tgetnum ("li")) <= 0 ! || (ncol=tgetnum ("co")) <= 0) { nrow = 24; ncol = 80; } SHAR_EOF if test 4313 -ne "`wc -c < 'sys/ultrix/ttyio.diff'`" then echo shar: error transmitting "'sys/ultrix/ttyio.diff'" '(should have been 4313 characters)' fi fi echo shar: done with directory "'sys/ultrix'" echo shar: done with directory "'sys'" if test ! -d 'tty' then echo shar: creating directory "'tty'" mkdir 'tty' fi if test ! -d 'tty/termcap' then echo shar: creating directory "'tty/termcap'" mkdir 'tty/termcap' fi echo shar: extracting "'tty/termcap/tty.c'" '(6971 characters)' if test -f 'tty/termcap/tty.c' then echo shar: will not over-write existing file "'tty/termcap/tty.c'" else cat << \SHAR_EOF > 'tty/termcap/tty.c' /* * Name: MicroEMACS * UNIX termcap/terminfo display driver * Version: 2 * Last edit: 16-Apr-86 * By: paul@ohio-state * cbosgd!osu-eddie!paul * * Termcap is a terminal information database and routines to describe * terminals on a UNIX system. This should be used ALLWAYS on a UNIX system * that has it. */ #include "def.h" #define BEL 0x07 /* BEL character. */ #define ESC 0x1B /* ESC character. */ #define LF 0x0A /* Line feed. */ extern int ttrow; extern int ttcol; extern int tttop; extern int ttbot; extern int tthue; int tceeol; /* Costs are set later */ int tcinsl; int tcdell; #define TCAPSLEN 315 char tcapbuf[TCAPSLEN]; char PC, *CM, *CL, *CE, *UP, *IM, /* insert mode */ *IC, /* insert a single space */ *EI, /* end insert mode */ *DC, *AL, /* add line */ *DL, /* del line */ *TI, /* term init -- start using cursor motion */ *TE, /* term end --- end using cursor motion */ *SO, *SE, *CD; /* * Initialize the terminal when the editor * gets started up. This is a no-op on the ANSI * display. On the SCALD display, it turns off the * half-screen scroll, because this appears to really * confuse the scrolling region firmware in the * display. */ static char tcbuf[1024]; ttinit() { char *getenv(); char *t, *p, *tgetstr(); char *tv_stype; char err_str[72]; if ((tv_stype = getenv("TERM")) == NULL) { puts("Environment variable TERM not defined!"); exit(1); } if((tgetent(tcbuf, tv_stype)) != 1) { sprintf(err_str, "Unknown terminal type %s!", tv_stype); puts(err_str); exit(1); } p = tcapbuf; t = tgetstr("pc", &p); if(t) PC = *t; CD = tgetstr("cd", &p); CM = tgetstr("cm", &p); CE = tgetstr("ce", &p); UP = tgetstr("up", &p); IM = tgetstr("im", &p); IC = tgetstr("ic", &p); EI = tgetstr("ei", &p); DC = tgetstr("dc", &p); AL = tgetstr("al", &p); DL = tgetstr("dl", &p); TI = tgetstr("ti", &p); TE = tgetstr("te", &p); SO = tgetstr("so", &p); SE = tgetstr("se", &p); if(CD == NULL || CM == NULL || CE == NULL || UP == NULL) { puts("This terminal is not powerful enough to run Micro Emacs\n"); exit(1); } if (!*CE) { tceeol = ncol; } else { tceeol = charcost(CE); } if (!*AL) { tcinsl = nrow * ncol; /* make this cost high enough that it */ /* won't ever happen */ } else { tcinsl = charcost(AL); } if (!*DL) { tcdell = nrow * ncol; /* make this cost high enough that it */ /* won't ever happen */ } else { tcdell = charcost(DL); } if (p >= &tcapbuf[TCAPSLEN]) { puts("Terminal description too big!\n"); exit(1); } if (*TI) tputs (TI); /* init the term */ } /* * 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. */ tttidy() { if (*TE) tputs (TE); /* set the term back to normal mode */ } /* * 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! */ ttmove(row, col) { if (ttrow!=row || ttcol!=col) { putpad(tgoto(CM, col, row)); ttrow = row; ttcol = col; } } /* * Erase to end of line. */ tteeol() { putpad(CE); } /* * Erase to end of page. */ tteeop() { putpad(CD); } /* * Make a noise. */ ttbeep() { ttputc(BEL); ttflush(); } /* * Insert nchunk blank line(s) onto the * screen, scrolling the last line on the * screen off the bottom. This is done with * a cluster of clever insert and delete commands, * because there are no scroll regions. */ ttinsl(row, bot, nchunk) { register int i; if (row == bot) { /* Case of one line insert is */ ttmove(row, 0); /* special */ tteeol(); return; } ttmove(1+bot-nchunk, 0); for (i=0; i NROW) newnrow = NROW; if (newncol < 1) newncol = 1; else if (newncol > NCOL) newncol = NCOL; nrow = newnrow; ncol = newncol; } static int cci; static fakec(c) /* fake char output for charcost() */ char c; { cci++; } charcost (s) /* calculate the cost of doing string s */ char *s; { cci = 0; tputs(s, nrow, fakec); return cci; } putpad(str) char *str; { tputs(str, 1, ttputc); } SHAR_EOF if test 6971 -ne "`wc -c < 'tty/termcap/tty.c'`" then echo shar: error transmitting "'tty/termcap/tty.c'" '(should have been 6971 characters)' fi fi echo shar: extracting "'tty/termcap/ttydef.h'" '(1285 characters)' if test -f 'tty/termcap/ttydef.h' then echo shar: will not over-write existing file "'tty/termcap/ttydef.h'" else cat << \SHAR_EOF > 'tty/termcap/ttydef.h' /* * Name: MicroEMACS * Digital ANSI terminal header file * Version: 29 * Last edit: 05-Feb-86 * By: rex::conroy * decvax!decwrl!dec-rhea!dec-rex!conroy */ #define GOSLING 1 /* Compile in fancy display. */ #define MEMMAP 0 /* Not memory mapped video. */ /* * Yes Bob, it's wrong for you. */ #define NROW 66 /* Rows. */ #define NCOL 132 /* Columns. */ /* * Special keys, as on the LK201, which is * a superset of the VT100. Originally I tried to keep the * numbers in LK201 escape sequence code, but it became too much * of a pain because of the keycodes greater than 31. * The codes are all just redefinitions for the standard extra * key codes. Using the standard names ensures that the * LK201 codes land in the right place. */ #define KUP K01 #define KDOWN K02 #define KLEFT K03 #define KRIGHT K04 #define KFIND K05 #define KINSERT K06 #define KREMOVE K07 #define KSELECT K08 #define KPREV K09 #define KNEXT K0A #define KF4 K0B #define KF6 K0C #define KF7 K0D #define KF8 K0E #define KF9 K0F #define KF10 K10 #define KF11 K11 #define KF12 K12 #define KF13 K13 #define KF14 K14 #define KHELP K15 #define KDO K16 #define KF17 K17 #define KF18 K18 #define KF19 K19 #define KF20 K1A #define KPF1 K1B #define KPF2 K1C #define KPF3 K1D #define KPF4 K1E SHAR_EOF if test 1285 -ne "`wc -c < 'tty/termcap/ttydef.h'`" then echo shar: error transmitting "'tty/termcap/ttydef.h'" '(should have been 1285 characters)' fi fi echo shar: extracting "'tty/termcap/ttykbd.c'" '(4209 characters)' if test -f 'tty/termcap/ttykbd.c' then echo shar: will not over-write existing file "'tty/termcap/ttykbd.c'" else cat << \SHAR_EOF > 'tty/termcap/ttykbd.c' /* * Name: MicroEMACS * Digital ANSI terminal keyboard. * Assumes LK201, which is OK on the VT100. * Version: 29 * Last edit: 05-Feb-86 * By: rex::conroy * decvax!decwrl!dec-rhea!dec-rex!conroy */ #include "def.h" #define ESC 0x1B /* Escape, arrows et al. */ #define AGRAVE 0x60 /* LK201 kludge. */ /* * The special keys on an LK201 send back * escape sequences of the general form [nnn~, where * nnn is a key code number. This table is indexed by the * nnn code to get the key code, which is used in the * binding table. The F4 key, and the F6 through F14 keys * have key codes. Also F17 through F20. Think of * help and do as special. */ short lk201map[] = { KRANDOM, KFIND, KINSERT, KREMOVE, KSELECT, KPREV, KNEXT, KRANDOM, KRANDOM, KRANDOM, KRANDOM, KRANDOM, KRANDOM, KRANDOM, KF4, KRANDOM, KRANDOM, KF6, KF7, KF8, KF9, KF10, KRANDOM, KF11, KF12, KF13, KF14, KRANDOM, KHELP, KDO, KRANDOM, KF17, KF18, KF19, KF20 }; /* * Names for the keys with basic keycode * between KFIRST and KLAST (inclusive). This is used by * the key name routine in "kbd.c". */ char *keystrings[] = { NULL, "Up", "Down", "Left", "Right", "Find", "Insert", "Remove", "Select", "Previous", "Next", "F4", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "Help", "Do", "F17", "F18", "F19", "F20", "PF1", "PF2", "PF3", "PF4", NULL }; /* * Read in a key, doing the low level mapping * of ASCII code to 11 bit code. This level deals with * mapping the special keys into their spots in the C1 * control area. The C0 controls go right through, and * get remapped by "getkey". */ getkbd() { register int c; register int n; loop: c = ttgetc(); if (c == ESC) { c = ttgetc(); if (c == '[') { c = ttgetc(); if (c == 'A') return (KUP); if (c == 'B') return (KDOWN); if (c == 'C') return (KRIGHT); if (c == 'D') return (KLEFT); if (c>='0' && c<='9') { /* LK201 functions. */ n = 0; do { n = 10*n + c - '0'; c = ttgetc(); } while (c>='0' && c<='9'); if (c=='~' && n<=34) { c = lk201map[n]; if (c != KRANDOM) return (c); goto loop; } } goto loop; } if (c == 'O') { c = ttgetc(); if (c == 'A') return (KUP); if (c == 'B') return (KDOWN); if (c == 'C') return (KRIGHT); if (c == 'D') return (KLEFT); if (c == 'P') return (KPF1); if (c == 'Q') return (KPF2); if (c == 'R') return (KPF3); if (c == 'S') return (KPF4); goto loop; } if (ISLOWER(c) != FALSE) /* Copy the standard */ c = TOUPPER(c); /* META code. */ if (c>=0x00 && c<=0x1F) c = KCTRL | (c+'@'); return (KMETA | c); } #if DO_METAKEY if (c & 0x80) /* if meta bit set on input */ return (KMETA | (c & 0x7f)); /* move bit from 8th to KMETA */ #endif return (c); } /* * Terminal specific keymap initialization. * Attach the special keys to the appropriate built * in functions. Bind all of the assigned graphics in the * DEC supplimental character set to "ins-self". * As is the case of all the keymap routines, errors * are very fatal. */ ttykeymapinit() { register SYMBOL *sp; register int i; keydup(KFIND, "search-again"); keydup(KHELP, "help"); keydup(KINSERT, "yank"); keydup(KREMOVE, "kill-region"); keydup(KSELECT, "set-mark"); keydup(KPREV, "back-page"); keydup(KNEXT, "forw-page"); keydup(KDO, "execute-macro"); keydup(KF17, "back-window"); keydup(KF18, "forw-window"); keydup(KF19, "enlarge-window"); keydup(KF20, "shrink-window"); keydup(KUP, "back-line"); keydup(KDOWN, "forw-line"); keydup(KRIGHT, "forw-char"); keydup(KLEFT, "back-char"); /* * Bind all GR positions that correspond * to assigned characters in the Digital multinational * character set to "ins-self". These characters may * be used just like any other character. */ if ((sp=symlookup("ins-self")) == NULL) abort(); for (i=0xA0; i<0xFF; ++i) { if (i!=0xA4 && i!=0xA6 && i!=0xAC && i!=0xAD && i!=0xAE && i!=0xAF && i!=0xB4 && i!=0xB8 && i!=0xBE && i!=0xF0 && i!=0xFE && i!=0xA0) { if (binding[i] != NULL) abort(); binding[i] = sp; ++sp->s_nkey; } } } SHAR_EOF if test 4209 -ne "`wc -c < 'tty/termcap/ttykbd.c'`" then echo shar: error transmitting "'tty/termcap/ttykbd.c'" '(should have been 4209 characters)' fi fi echo shar: done with directory "'tty/termcap'" echo shar: done with directory "'tty'" exit 0 # End of shell archive