floydd@attctc.Dallas.TX.US (Floyd Davidson) (11/17/89)
# This is part 1 of 2 of the patch kit for MicroEMACS on the UNIX-PC. # # This patch kit requires the original distribution files for # MicroEMACS 3.10. The Readme file lists a free access BBS # from which the files may be downloaded. # # This shar file contains: Readme, Makefile, and unixpc.c # # #----- cut here ----- #!/bin/sh # # TO EXTRACT: remove the header and type "sh filename" # if `test ! -s ./Readme` then echo "\nWriting ./Readme" echo "Original file: 3476 Nov 11 15:11 ./Readme" cat > ./Readme << '!rebmevoN!9891!' >>>>>From main.c: "* MicroEMACS 3.10 * written by Daniel M. Lawrence * based on code by Dave G. Conroy. * * (C)opyright 1988,1989 by Daniel M. Lawrence * MicroEMACS 3.10 can be copied and distributed freely for any * non-commercial purposes. MicroEMACS 3.10 can only be incorporated * into commercial software with the permission of the current author. *" Emacs.pat and original code in unixpc.c are unconditionally released to the Public Domain. Emacs.pat is a patch file to configure MicroEMACS 3.10 for a UNIX-PC. Changes to distribution files are listed below. MicroEMACS 3.10 is available in *.arc files from "The Programmers' Room" at (317) 742-5533. The files are in MSDOS format and must be renamed to lower case and have all the ^M's removed. Once that is done, use patch, or manually edit, to convert the files per emacs.pat. Two new files: unixpc.c and Makefile. Unixpc.c is the UNIX-PC terminal driver. Makefile is configured for 'gcc'. Reconfiguration of Makefile for 'cc' is trivial, and one change must be made to estruct.h: change the GCC define from '1' to '0'. In addition to the distribution files the Makefile requires the use of Doug Gwyn's dirent directory library and header files. Caveats: This is essentially a beta version. It is also configured very much to the author's personal taste, which will likely irritate yours. Change the key bindings. If you prefer function and special keys to be distinct for <Shift> and/or <Ctrl>, change fkeyd() in unixpc.c by adding more case statements and removing to the uppercase conversion of the escape sequence. If the function key bindings are changed in ebind.h it is recommended to change the default screen labels in unixpc.c. This can be done by macros or in .emacsrc, but startup will be slowed down. ************************************************************************* Changes to bind.c: Cast 'errorm' to 'char *'. Change setkey() to setakey() to avoid shared lib conflict. Change crypt() to krypt() to avoid shared lib conflict. Changes to bind.h: Ifdef out IBMPC function key bindings, ifdef in UNIXPC bindings. Changes to estruct.h: Define USG, UNIX, TERMCAP to TRUE. Define COLOR to FALSE. Add and define GCC and UNIXPC to TRUE. Add conditional to define 'CONST' as 'const' for (UNIX && GCC) or '' if (UNIX && !GCC). Add conditional to define ETYPE as 'struct' for UNIX. Changes to etype.h: Add 'int' type to all funtions with only 'PASCAL NEAR' or 'CDECL NEAR'. Changes to eval.c: Cast 'errorm' to 'char *'. Cast 'falsem' to 'char *'. Cast 'truem' to 'char *'. Add EVTLABEL# and EVBLABEL# to case statements for setting and returning function label variables. Change setkey() references to setakey(). Changes to evar.h: Add names for function label variables. Add numbers for function label variables. Add declaration for setflabel() function. Changes to isearch.c: Add 'int' type to reeat(). Changes to region.c: Cast 'errorm' to 'char *'. Changes to tcap.c: Change 'UP' to 'UPP' to avoid conflict with shared lib. Change 'PC' to 'PCC' to avoid conflict with shared lib. Changes to window.c: Add call to wndwopen() to refresh(). _______________________________________________________ Floyd L. Davidson attctc!floydd 8347 Richardson Hwy. jolnet!floydd Salcha, AK 99714 (907) 488-3294 _______________________________________________________ !rebmevoN!9891! else echo "\nWill not over write ./Readme" fi ls -l ./Readme # if `test ! -s ./Makefile` then echo "\nWriting ./Makefile" echo "Original file: 2438 Nov 11 15:11 ./Makefile" cat > ./Makefile << '!rebmevoN!9891!' # # Makefile -- MicroEmacs 3.10 / UNIX-PC 7300/3B1 # #################################################### # # compiler selection (uncomment one or the other) # #################################################### # uncomment only for 'gcc' # also, in file estruct.h define GCC=1 CC =gcc LD =gcc CFLAGS =-O LDFLAGS =-s -shlib # #################################################### # uncomment only for 'cc' # also, in file estruct.h define GCC=0 #CC =cc #LD =ld #CFLAGS =-O #LDFLAGS = /lib/crt0s.o /lib/shlib.ifile #################################################### OFILES= basic.o bind.o buffer.o char.o crypt.o display.o \ eval.o exec.o file.o fileio.o input.o isearch.o \ line.o main.o mouse.o random.o region.o \ search.o tcap.o unixpc.o window.o word.o CFILES= basic.c bind.c buffer.c char.c crypt.c display.c \ eval.c exec.c file.c fileio.c input.c isearch.c \ line.c main.c mouse.c random.c region.c \ search.c tcap.c unixpc.c window.c word.c HFILES1=estruct.h etype.h edef.h elang.h emacs: $(OFILES) $(LD) $(LDFLAGS) $(OFILES) -ldirent -o em1 mv em1 emacs basic.o: basic.c $(HFILES1) ${CC} ${CFLAGS} -c basic.c bind.o: bind.c $(HFILES1) epath.h ${CC} ${CFLAGS} -c bind.c buffer.o: buffer.c $(HFILES1) ${CC} ${CFLAGS} -c buffer.c char.o: char.c $(HFILES1) ${CC} ${CFLAGS} -c char.c crypt.o: crypt.c $(HFILES1) ${CC} ${CFLAGS} -c crypt.c display.o: display.c $(HFILES1) ${CC} ${CFLAGS} -c display.c eval.o: eval.c $(HFILES1) evar.h ${CC} ${CFLAGS} -c eval.c exec.o: exec.c $(HFILES1) ${CC} ${CFLAGS} -c exec.c file.o: file.c $(HFILES1) ${CC} ${CFLAGS} -c file.c fileio.o: fileio.c $(HFILES1) ${CC} ${CFLAGS} -c fileio.c input.o: input.c $(HFILES1) ${CC} ${CFLAGS} -c input.c isearch.o: isearch.c $(HFILES1) ${CC} ${CFLAGS} -c isearch.c line.o: line.c $(HFILES1) ${CC} ${CFLAGS} -c line.c main.o: main.c $(HFILES1) efunc.h ebind.h ${CC} ${CFLAGS} -c main.c mouse.o: mouse.c $(HFILES1) efunc.h ebind.h ${CC} ${CFLAGS} -c mouse.c random.o: random.c $(HFILES1) ${CC} ${CFLAGS} -c random.c region.o: region.c $(HFILES1) ${CC} ${CFLAGS} -c region.c search.o: search.c $(HFILES1) ${CC} ${CFLAGS} -c search.c tcap.o: tcap.c $(HFILES1) ${CC} ${CFLAGS} -c tcap.c unixpc.o: unixpc.c $(HFILES1) ${CC} ${CFLAGS} -c unixpc.c window.o: window.c $(HFILES1) ${CC} ${CFLAGS} -c window.c word.o: word.c $(HFILES1) ${CC} ${CFLAGS} -c word.c !rebmevoN!9891! else echo "\nWill not over write ./Makefile" fi ls -l ./Makefile # if `test ! -s ./unixpc.c` then echo "\nWriting ./unixpc.c" echo "Original file: 25254 Nov 11 15:06 ./unixpc.c" cat > ./unixpc.c << '!rebmevoN!9891!' /* unixpc.c -- unix.c for the UNIX-PC 7300/3B1 Operating specific I/O and Spawning functions under UNIX V7, BSD4.2/3, System V, SUN OS and SCO XENIX for MicroEMACS 3.10 (C)opyright 1988 by Daniel M. Lawrence Mouse and function key support for the AT&T Unix-PC 7300/3b1. Modified from MicroEMACS 3.10 distribution file unix.c. Modifications are Public Domain. ************************************************************************** Default function key screen labels should be customized for whatever bindings are set in ebind.h. They can be changed with macros or by .emacsrc, but it does make startup slowwww. ************************************************************************** DISCLAIMER: This was written to satisfy my personal editor needs (spelled r-e-l-i-g-i-o-n). E.g. having all function and special keys the same whether or not the shift or control keys are pressed. Others may want them decoded separately. Floyd L. Davidson attctc!floydd 8347 Richardson Hwy. jolnet!floydd Salcha, AK 99714 */ /* * Support for the Unix-Pc mouse, function and special keys * is implemented by converting escape code sequences to * appropriate characters or sequences for MicroEMACS. * * Function and special keys are defined such that * <Ctrl> or <Shift> does NOT change the key definition. * * Mouse button functions are defined in mouse.c. * Function and special key bindings are defined in ebind.h. * * The following table shows the (SPEC|character) that each key * sends to MicroEMACS: * * MicroEMACS KEYMAP * Unix-Pc 7300/3b1 * * ClearLine 'O' Rstrt/Ref 'P' F1 '1' * Creat 'T' Save 'U' F2 '2' * Undo 'Y' Redo 'Z' F3 '3' * Find 'd' Rplac 'e' F4 '3' * Move 'C' Copy 'D' F5 '5' * Dlete 'E' DleteChar 'F' F6 '6' * Slect/Mark 'I' InputMode 'J' F7 '7' * F8 '8' * * Exit 'Q' Msg ---- Help 'S' * Suspd ---- Rsume ---- Opts 'X' * Cmd 'a' Close/Open 'b' Cancl 'c' * Print 'f' Clear/Rfrsh 'A' Page 'i' * Beg 'B' Home 'M' End 'N' * Prev 'G' UpArrow 'g' Next 'H' * LeftArrow 'K' DownArrow 'h' RghtArrow 'L' * * * Keys marked '----' are owned by the system (ie. ph and smgr). * In addition Sh-Print is owned by the system. * */ #include <stdio.h> #include <track.h> #include "estruct.h" #include "etype.h" #include "edef.h" #include "elang.h" #include <termio.h> #include <fcntl.h> #include <dirent.h> #include <sys/stat.h> char kbdq; /* char we've already read */ int mouserow; /* mouse row */ int mousecol; /* mouse column */ int lbutton; /* flag that left button changed */ int mbutton; /* flag that middle button changed */ int rbutton; /* flag that right button changed */ int nullflag; /* flag a null, not a mouse action */ int lkey; /* last key action */ int kbdflgs; /* saved keyboard fd flags */ int kbdpoll; /* in O_NDELAY mode */ int kbdqp; /* there is a char in kbdq */ int mvalue; /* mouse return value */ int kbdch; /* char to return */ int fkeyd(); /* return decoded/encoded keystroke */ int getmouse(); /* decodes mouse escape sequences */ struct termio otermio; /* original terminal characteristics */ struct termio ntermio; /* charactoristics to use inside */ #define MAXSLK 79 #define SLKTEXT " %s %s %s %s %s %s %s %s " struct utdata utd; /* new window data structure */ char utd1old[MAXSLK];/* original window labels, line 1 */ char utd2old[MAXSLK];/* original window labels, line 2 */ struct umdata mdnew; /* new mouse info data structure */ struct umdata mdold; /* original mouse info data structure */ #ifdef ESC #undef ESC #endif #define ESC 0x1b /* * default function key labels. */ char *deflabels[] = { /* strings for the top line of labels */ " exec", /* F1 key */ " begin", /* F2 key */ " end", /* F3 key */ " ", /* F4 key */ " ", /* F5 key */ " ", /* F6 key */ " ", /* F7 key */ " ", /* F8 key */ /* strings for the botton line of labels */ " macro", /* F1 key */ " macro", /* F2 key */ " macro", /* F3 key */ " ", /* F4 key */ " ", /* F5 key */ " ", /* F6 key */ " ", /* F7 key */ " " /* F8 key */ }; char *flabels[16]; /* Labels for function keys. These may be changed using * environmental variables $tlabel1 to $tlabel8 for the * top line and $blabel1 to $blabel8 for the bottom line. * Only 8 characters are used, any excess is discarded. * * setflabel() returns a pointer to the label string, and * sets a new string. */ char *setflabel(s,n) char *s; int n; { char buffer[18]; unsigned int i; static int flag = 0; if (!flag) { for (i=0;i < 16; ++i) { flabels[i] = (char *) malloc(9); if (flabels[i] == (char *)NULL) { printf("memory fault"); exit(1); } strncpy(buffer,deflabels[i],8); buffer[8] = '\0'; strcat(buffer," "); strncpy(flabels[i],buffer,8); flabels[i][8] = '\0'; } flag = 1; } if (s != (char *) NULL) { /* truncate and/or fill labels to exactly eight characters */ strncpy(buffer,s,8); buffer[8] = '\0'; strcat(buffer," "); strncpy(flabels[n],buffer,8); flabels[n][8] = '\0'; } return(flabels[n]); } /* * gets and parses a mouse input escape sequence . */ int getmouse() { register int ccnt; unsigned char mque[15]; /* mouse sequence que */ unsigned char *qptr; /* ptr into kbdque[] */ unsigned char *xptr[4]; /* ptrs to mouse data segments */ unsigned int i = 0; /* token counter */ unsigned int k = 0; /* char counter */ int ckey; /* current key action */ int key; /* individual key */ char *s1,*s2; xptr[i++] = &mque[0]; for (k=0;k < 15;++k) { ccnt = read(0, &mque[k], 1); /* get another character */ if (!ccnt) return; /* no char, must be error */ if (';' == mque[k]) { mque[k] = '\0'; xptr[i++] = &mque[k+1]; /* set next token ptr */ } else if ('M' == mque[k]) { mque[k] = '\0'; break; /* end of data */ } else if ('\0' == mque[k]) { ++i; /* flag error */ break; } } k = atoi(xptr[3]); mousecol = (atoi(xptr[0])+8) / 9; mouserow = (atoi(xptr[1])+11) / 12; if (!mousecol) mousecol = 1; if (!mouserow) mousecol = 1; /* * need to do this different. Keep a new flag and and old * flag for each one. set the button flags if they have * changed. */ ckey = atoi(xptr[2]); if(2 == k) ckey = lkey - ckey; if(1 == k) ckey = ckey - lkey; lkey = atoi(xptr[2]); lbutton = ckey & 4; mbutton = ckey & 2; rbutton = ckey & 1; mvalue = k; return(TRUE); } /* * decode function key escape sequence to a single chararacter. * * All keys are tranlated to the same character whether * unshifted or Shift or Ctrl. * */ int fkeyd() { register int ccnt; char kbdque[4]; /* set O_NDELAY */ if (!kbdpoll && fcntl(0, F_SETFL, kbdflgs | O_NDELAY) < 0) return(FALSE); kbdpoll = TRUE; ccnt=read(0, kbdque, 2); /* get 2 more chars */ if (ccnt < 1) return (ESC); /* only an ESC, return it */ kbdque[ccnt] = 0; /* terminate it */ /*****************************************************************\ * Delete this statement and add case statements for lower case if * * Shift or Ctrl is to be decoded distinctly. * \*****************************************************************/ /* convert to upper case (except 'z') */ kbdque[1] = ( (kbdque[1] >= 'a') && (kbdque[1] < 'z') ) ? kbdque[1] - 0x20 : kbdque[1]; switch (kbdque[0]) { /* \ENx */ case 'N': switch (kbdque[1]) { /* Clear/Rfrsh */ case 'A': ccnt = (SPEC | 'A');break; /* s-Beg */ case 'B': ccnt = (SPEC | 'B');break; /* Move */ case 'C': ccnt = (SPEC | 'C');break; /* Copy */ case 'D': ccnt = (SPEC | 'D');break; /* Dlete */ case 'E': ccnt = (SPEC | 'E');break; /* DleteChar */ case 'F': ccnt = (SPEC | 'F');break; /* Prev */ case 'G': ccnt = (SPEC | 'G');break; /* Next */ case 'H': ccnt = (SPEC | 'H');break; /* Slect/Mark */ case 'I': ccnt = (SPEC | 'I');break; /* InputMode */ case 'J': ccnt = (SPEC | 'J');break; /* s-LeftArrow */ case 'K': ccnt = (SPEC | 'K');break; /* s-RghtArrow */ case 'L': ccnt = (SPEC | 'L');break; /* s-Home */ case 'M': ccnt = (SPEC | 'M');break; /* s-End */ case 'N': ccnt = (SPEC | 'N');break; /* invalid sequence */ default : ccnt = (SPEC | '!');break; };break; /* \EOx */ case 'O': switch (kbdque[1]) { /* ClearLine */ case 'A': ccnt = (SPEC | 'O');break; /* Rstrt/Ref */ case 'B': ccnt = (SPEC | 'P');break; /* F1 */ case 'C': ccnt = (SPEC | '1');break; /* F2 */ case 'D': ccnt = (SPEC | '2');break; /* F3 */ case 'E': ccnt = (SPEC | '3');break; /* F4 */ case 'F': ccnt = (SPEC | '4');break; /* F5 */ case 'G': ccnt = (SPEC | '5');break; /* F6 */ case 'H': ccnt = (SPEC | '6');break; /* F7 */ case 'I': ccnt = (SPEC | '7');break; /* F8 */ case 'J': ccnt = (SPEC | '8');break; /* Exit */ case 'K': ccnt = (SPEC | 'Q');break; /* Msg */ case 'L': ccnt = (SPEC | 'R');break; /* Help */ case 'M': ccnt = (SPEC | 'S');break; /* Creat */ case 'N': ccnt = (SPEC | 'T');break; /* Save */ case 'O': ccnt = (SPEC | 'U');break; /* Suspd */ case 'P': ccnt = (SPEC | 'V');break; /* Rsume */ case 'Q': ccnt = (SPEC | 'W');break; /* Opts */ case 'R': ccnt = (SPEC | 'X');break; /* Undo */ case 'S': ccnt = (SPEC | 'Y');break; /* Redo */ case 'T': ccnt = (SPEC | 'Z');break; /* Cmd */ case 'U': ccnt = (SPEC | 'a');break; /* Close/Open */ case 'V': ccnt = (SPEC | 'b');break; /* Cancl */ case 'W': ccnt = (SPEC | 'c');break; /* Find */ case 'X': ccnt = (SPEC | 'd');break; /* Rplac */ case 'Y': ccnt = (SPEC | 'e');break; /* Print */ case 'z': ccnt = (SPEC | 'f');break; /* invalid sequence */ default : ccnt = (SPEC | '@');break; };break; /* \EPx */ case 'P': switch (kbdque[1]) { /* PF1 '1'*/ case 'A': ccnt = (SPEC | 'G');break; /* PF2 '2'*/ case 'B': ccnt = (SPEC | 'g');break; /* PF3 '3'*/ case 'C': ccnt = (SPEC | 'H');break; /* PF4 '4'*/ case 'D': ccnt = (SPEC | 'B');break; /* PF5 '5'*/ case 'E': ccnt = (SPEC | 'M');break; /* PF6 '6'*/ case 'F': ccnt = (SPEC | 'N');break; /* PF7 '7'*/ case 'G': ccnt = (SPEC | 'f');break; /* PF8 '8'*/ case 'H': ccnt = (SPEC | 'A');break; /* PF9 '9'*/ case 'I': ccnt = (SPEC | 'k');break; /* PF10 '0'*/ case 'J': ccnt = (SPEC | 'h');break; /* PF11 '-'*/ case 'K': ccnt = (SPEC | 'K');break; /* PF12 '='*/ case 'L': ccnt = (SPEC | 'L');break; /* invalid sequence */ default : ccnt = (SPEC | '#');break; };break; /* \E[x */ case '[': switch (kbdque[1]) { /* UpArrow */ case 'A': ccnt = (SPEC | 'g');break; /* DnArrow */ case 'B': ccnt = (SPEC | 'h');break; /* RghtArrow */ case 'C': ccnt = (SPEC | 'L');break; /* LeftArrow */ case 'D': ccnt = (SPEC | 'K');break; /* Home */ case 'H': ccnt = (SPEC | 'M');break; /* s/^ Clear/Rfrsh */ case 'J': ccnt = (SPEC | 'A');break; /* Roll up */ case 'S': ccnt = (SPEC | 'h');break; /* Roll down */ case 'T': ccnt = (SPEC | 'g');break; /* Page */ case 'U': ccnt = (SPEC | 'i');break; /* s-Page */ case 'V': ccnt = (SPEC | 'i');break; /* s-Tab */ case 'Z': ccnt = ('\011');break; /* Mouse */ case '?': if(getmouse()) { ccnt = '\0'; nullflag = 2; /* flag null sent */ break; } else {ccnt = (SPEC | '*');break;} /* invalid sequence */ default : ccnt = (SPEC | '$');break; };break; /* \Ex */ /* Beg */ case '9': ccnt = (SPEC | 'B');break; /* End */ case '0': ccnt = (SPEC | 'N');break; /* invalid sequence */ default: ccnt = (SPEC | '%');break; } return (ccnt); } /* * Set up the terminal. */ ttopen() { struct uwdata uw; void wndwopen(); ioctl(0, TCGETA, &otermio); /* save old settings */ ntermio.c_iflag = 0; /* setup new settings */ ntermio.c_oflag = 0; ntermio.c_cflag = otermio.c_cflag; ntermio.c_lflag = 0; ntermio.c_line = otermio.c_line; ntermio.c_cc[VMIN] = 1; ntermio.c_cc[VTIME] = 1; ioctl(0, TCSETAW, &ntermio); /* and activate them */ kbdflgs = fcntl( 0, F_GETFL, 0 ); kbdpoll = FALSE; /* on all screens we are not sure of the initial position of the cursor */ ttrow = 999; ttcol = 999; /* See if it's a bitmapped display */ if ( 0 == ioctl(1,WIOCGETD, &uw)) { wndwopen(TRUE); } } /* * If the tty is a windowed device we assume is also has a mouse, * and initialize the mouse and screen labels. When called with * a saveflag value TRUE all label and mouse data is saved, otherwise * not. */ void wndwopen(saveflag) { char slkbuf1[81]; char slkbuf2[81]; char *ptr0,*ptr1; char label[16][18]; unsigned int i; /* turn on the mouse */ if (saveflag) { ioctl(0, WIOCGETMOUSE, &mdold); /* save original data */ } ioctl(0, WIOCGETMOUSE, &mdnew); mdnew.um_icon = (struct icon *)NULL; /* use default pointer */ mdnew.um_flags = MSDOWN | MSUP; /* sent up/down data */ ioctl(0, WIOCSETMOUSE, &mdnew); /* set up function key labels */ utd.ut_num = WTXTSLK1; ioctl(0, WIOCGETTEXT, &utd); /* save original data */ if (saveflag) { ptr0=utd1old; ptr1=utd.ut_text; strncpy(ptr0,ptr1,MAXSLK); utd.ut_num = WTXTSLK2; ioctl(0, WIOCGETTEXT, &utd); ptr0=utd2old; ptr1=utd.ut_text; strncpy(ptr0,ptr1,MAXSLK); } /* strings for the top line of labels */ sprintf(slkbuf1,SLKTEXT, /* make new labels */ setflabel(0,0), setflabel(0,1), setflabel(0,2), setflabel(0,3), setflabel(0,4), setflabel(0,5), setflabel(0,6), setflabel(0,7) ); /* strings for the botton line of labels */ sprintf(slkbuf2,SLKTEXT, setflabel(0,8), setflabel(0,9), setflabel(0,10), setflabel(0,11), setflabel(0,12), setflabel(0,13), setflabel(0,14), setflabel(0,15) ); slkbuf1[80] = slkbuf2[80] = '\0'; winit(); wslk(0, 0, slkbuf1, slkbuf2, 0); wdelete(wgetsel()); } /* * Restore original terminal device state. */ ttclose() { struct uwdata uw; void wndwclose(); ioctl(0, TCSETA, &otermio); /* restore terminal */ fcntl(0, F_SETFL, kbdflgs); /* See if it's a bitmapped display */ if ( 0 == ioctl(1,WIOCGETD, &uw)) { wndwclose(); } } /* * Close window, restore original mouse and label data. */ void wndwclose() { char *ptr0,*ptr1; ioctl(0, WIOCSETMOUSE, &mdold); /* restore mouse */ ptr0 = utd.ut_text; ptr1 = utd1old; strncpy(ptr0,ptr1,MAXSLK); utd.ut_num = WTXTSLK1; ioctl(0, WIOCSETTEXT, &utd); /* restore labels */ ptr0 = utd.ut_text; ptr1 = utd2old; utd.ut_num = WTXTSLK2; strncpy(ptr0,ptr1,MAXSLK); ioctl(0, WIOCSETTEXT, &utd); } /* * Write a character to the display. */ ttputc(c) { fputc(c, stdout); } /* * Flush terminal buffer. */ ttflush() { fflush(stdout); } /* TTGETC: Read a character from the terminal, performing no editing and doing no echo at all. */ ttgetc() { /* return queued character first */ if (kbdqp) { kbdqp = FALSE; return (kbdch); } /* return nulls or mouse sequences */ if ( lbutton | mbutton | rbutton | nullflag ) { ++nullflag; if ( (nullflag > 1) && !(lbutton|mbutton|rbutton) ) nullflag = 1; switch (nullflag) { case (0): nullflag = 0;return('\0');/* for real null */ case (1): nullflag = 0;break; case (2): nullflag = 0;return('\0');/* mark esc seq. */ case (3): return(MOUS >> 8); /* prefix a mouse */ case (4): return(mousecol-1); /* x-axis */ case (5): return(mouserow-1); /* y-axis */ case (6): mvalue += (0x60); /* what happened */ nullflag = 0; if (lbutton) { lbutton = 0; return(mvalue); } else if (mbutton) { mbutton = 0; return(mvalue+2); } else if (rbutton) { rbutton = 0; return(mvalue+4); } /* end of case (5) */ default: nullflag = 0;break; /* error if we do this */ } /* switch (nullflag) */ } /* if flags */ /* the character que is empty, no nulls are needed and no mouse seq. */ /* so turn off O_NDELAY and wait patiently... */ if (kbdpoll && fcntl(0, F_SETFL, kbdflgs) < 0) return(FALSE); kbdpoll = FALSE; /* no polling */ while (read(0,&kbdq,1) < 1) ; kbdch = kbdq & 0x7f; /* make Reset/Break a <DEL> */ if(!kbdch) nullflag = -1; /* send two nulls for a null */ if(kbdch == ESC) kbdch = fkeyd(); /* decode possible /E seq */ return(kbdch); } /* typahead: Check to see if any characters are already in the keyboard buffer */ typahead() { /* already queued up */ if (kbdqp) { return (TRUE); } /* mouse sequence is processing, que it */ if (lbutton | mbutton | rbutton | nullflag) { kbdch = ttgetc(); kbdqp = TRUE; return (TRUE); } /* set O_NDELAY and get a character to que */ if (!kbdpoll && fcntl(0, F_SETFL, kbdflgs | O_NDELAY) < 0) return(FALSE); kbdpoll = TRUE; kbdqp = (1 == (read(0,&kbdq,1))); if(kbdqp) { kbdch = kbdq & 0x7f; /* change the Reset/Break key*/ if(!kbdch) nullflag = -1; /* send two nulls for a null */ if (kbdch == ESC) { kbdch = fkeyd(); /* decode possible /E seq */ } } return(kbdqp); } /* * Create a subjob with a copy of the command intrepreter in it. When the * command interpreter exits, mark the screen as garbage so that you do a full * repaint. Bound to "^X C". */ spawncli(f, n) { register char *cp; char *getenv(); /* don't allow this command if restricted */ if (restflag) return(resterr()); movecursor(term.t_nrow, 0); /* Seek to last line. */ TTflush(); TTclose(); /* stty to old settings */ if ((cp = getenv("SHELL")) != NULL && *cp != '\0') system(cp); else system("exec /bin/sh"); sgarbf = TRUE; sleep(2); TTopen(); return(TRUE); } /* * Run a one-liner in a subjob. When the command returns, wait for a single * character to be typed, then mark the screen as garbage so a full repaint is * done. Bound to "C-X !". */ spawn(f, n) { register int s; char line[NLINE]; /* don't allow this command if restricted */ if (restflag) return(resterr()); if ((s=mlreply("shell-command: ", line, NLINE)) != TRUE) return(s); TTputc('\n'); /* Already have '\r' */ TTflush(); TTclose(); /* stty to old modes */ system(line); TTopen(); TTflush(); /* if we are interactive, pause here */ if (clexec == FALSE) { mlwrite("[End]"); TTflush(); tgetc(); } sgarbf = TRUE; return(TRUE); } /* * Run an external program with arguments. When it returns, wait for a single * character to be typed, then mark the screen as garbage so a full repaint is * done. Bound to "C-X $". */ execprg(f, n) { register int s; char line[NLINE]; /* don't allow this command if restricted */ if (restflag) return(resterr()); if ((s=mlreply("shell-command: ", line, NLINE)) != TRUE) return(s); TTputc('\n'); /* Already have '\r' */ TTflush(); TTclose(); /* stty to old modes */ system(line); TTopen(); mlwrite("[End]"); /* Pause. */ TTflush(); while ((s = tgetc()) != '\r' && s != ' ') ; sgarbf = TRUE; return(TRUE); } /* * Pipe a one line command into a window * Bound to ^X @ */ pipecmd(f, n) { register int s; /* return status from CLI */ register WINDOW *wp; /* pointer to new window */ register BUFFER *bp; /* pointer to buffer to zot */ char line[NLINE]; /* command line send to shell */ static char bname[] = "command"; static char filnam[NFILEN] = "command"; /* don't allow this command if restricted */ if (restflag) return(resterr()); /* get the command to pipe in */ if ((s=mlreply("pipe-command: ", line, NLINE)) != TRUE) return(s); /* get rid of the command output buffer if it exists */ if ((bp=bfind(bname, FALSE, 0)) != FALSE) { /* try to make sure we are off screen */ wp = wheadp; while (wp != NULL) { if (wp->w_bufp == bp) { onlywind(FALSE, 1); break; } wp = wp->w_wndp; } if (zotbuf(bp) != TRUE) return(FALSE); } TTputc('\n'); /* Already have '\r' */ TTflush(); TTclose(); /* stty to old modes */ strcat(line,">"); strcat(line,filnam); system(line); TTopen(); TTflush(); sgarbf = TRUE; s = TRUE; if (s != TRUE) return(s); /* split the current window to make room for the command output */ if (splitwind(FALSE, 1) == FALSE) return(FALSE); /* and read the stuff in */ if (getfile(filnam, FALSE) == FALSE) return(FALSE); /* make this window in VIEW mode, update all mode lines */ curwp->w_bufp->b_mode |= MDVIEW; wp = wheadp; while (wp != NULL) { wp->w_flag |= WFMODE; wp = wp->w_wndp; } /* and get rid of the temporary file */ unlink(filnam); return(TRUE); } rename(old, new) /* change the name of a file */ char *old; /* original file name */ char *new; /* new file name */ { link(old, new); unlink(old); } /* * filter a buffer through an external program * Bound to ^X # */ filter(f, n) { register int s; /* return status from CLI */ register BUFFER *bp; /* pointer to buffer to zot */ char line[NLINE]; /* command line send to shell */ char tmpnam[NFILEN]; /* place to store real file name */ static char bname1[] = "fltinp"; static char filnam1[] = "fltinp"; static char filnam2[] = "fltout"; /* don't allow this command if restricted */ if (restflag) return(resterr()); if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ /* get the filter name and its args */ if ((s=mlreply("filter-buffer: ", line, NLINE)) != TRUE) return(s); /* setup the proper file names */ bp = curbp; strcpy(tmpnam, bp->b_fname); /* save the original name */ strcpy(bp->b_fname, bname1); /* set it to our new one */ /* write it out, checking for errors */ if (writeout(filnam1) != TRUE) { mlwrite("[Cannot write filter file]"); strcpy(bp->b_fname, tmpnam); return(FALSE); } TTputc('\n'); /* Already have '\r' */ TTflush(); TTclose(); /* stty to old modes */ strcat(line," <fltinp >fltout"); system(line); TTopen(); TTflush(); sgarbf = TRUE; s = TRUE; /* on failure, escape gracefully */ if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) { mlwrite("[Execution failed]"); strcpy(bp->b_fname, tmpnam); unlink(filnam1); unlink(filnam2); return(s); } /* reset file name */ strcpy(bp->b_fname, tmpnam); /* restore name */ bp->b_flag |= BFCHG; /* flag it as changed */ /* and get rid of the temporary file */ unlink(filnam1); unlink(filnam2); return(TRUE); } /* * Return a system dependant string with the current time. */ char * timeset() { register char *sp; /* temp string pointer */ char buf[16]; /* time data buffer */ extern char *ctime(); time(buf); sp = ctime(buf); sp[strlen(sp)-1] = 0; return(sp); } #if COMPLET /* FILE Directory routines */ DIR *dirptr = NULL; /* pointer to the current directory being searched */ char path[NFILEN]; /* path of file to find */ char rbuf[NFILEN]; /* return file buffer */ char *nameptr; /* ptr past end of path in rbuf */ /* do a wild card directory search (for file name completion) */ char * getffile(fspec) char *fspec; /* pattern to match */ { register int index; /* index into various strings */ register int point; /* index into other strings */ register int extflag; /* does the file have an extention? */ /* first parse the file path off the file spec */ strcpy(path, fspec); index = strlen(path) - 1; while (index >= 0 && (path[index] != '/' && path[index] != '\\' && path[index] != ':')) --index; path[index+1] = 0; /* check for an extension */ point = strlen(fspec) - 1; extflag = FALSE; while (point >= 0) { if (fspec[point] == '.') { extflag = TRUE; break; } point--; } /* open the directory pointer */ if (dirptr != NULL) { closedir(dirptr); dirptr = NULL; } dirptr = opendir(path); if (dirptr == NULL) return(NULL); strcpy(rbuf, path); nameptr = &rbuf[strlen(rbuf)]; /* and call for the first file */ return(getnfile()); } char * getnfile() { register struct dirent *dp; /* directory entry pointer */ register int index; /* index into various strings */ struct stat fstat; /* and call for the next file */ nxtdir: dp = readdir(dirptr); if (dp == NULL) return(NULL); /* check to make sure we skip directory entries */ strcpy(nameptr, dp->d_name); stat(rbuf, &fstat); if ((fstat.st_mode & S_IFMT) != S_IFREG) goto nxtdir; /* return the next file name! */ return(rbuf); } #else char * getffile(fspec) char *fspec; /* file to match */ { return(NULL); } char * getnfile() { return(NULL); } #endif !rebmevoN!9891! else echo "\nWill not over write ./unixpc.c" fi ls -l ./unixpc.c # echo "\nPart 1 Finished...\n"