home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
001-099
/
ff093.lzh
/
MicroEmacs
/
source
/
src.arc
/
termio.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-08-16
|
17KB
|
624 lines
/*
* The functions in this file negotiate with the operating system for
* characters, and write characters in a barely buffered fashion on the display.
* All operating systems.
*/
#include <stdio.h>
#include "estruct.h"
#include "edef.h"
#if MEGAMAX & ST520
overlay "termio"
#endif
#if AMIGA
#undef TRUE
#undef FALSE
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/tasks.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <devices/console.h>
#include <devices/conunit.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <graphics/clip.h>
#include <graphics/view.h>
#include <graphics/rastport.h>
#include <graphics/layers.h>
#include <graphics/text.h>
#include <intuition/intuition.h>
#define CSI 0x9b
#define AMG_MAXBUF 4608L /* worst case size */
extern struct IntuitionBase *IntuitionBase; /* library bases */
extern struct GfxBase *GfxBase;
extern struct Window *EmacsWindow; /* Our window */
extern struct MsgPort *consoleport; /* I/O port */
extern struct IOStdReq *consoleWriteMsg; /* I/O messages */
extern struct IOStdReq *consoleReadMsg;
extern struct Window *savewindow;
extern char *itoa(); /* we decide the */
extern LONG newsize(); /* the screen size */
extern LONG newwidth(); /* a startup */
extern VOID CursorOn(), /* these guys help */
CursorOff(); /* speed up screen */
/* writes */
extern VOID *OpenLibrary();
extern LONG OpenConsole();
extern struct Task *FindTask();
extern struct Window *InitWindow();
extern struct MsgPort *CreatePort();
extern struct IOStdReq *CreateStdIO();
extern UWORD getrows(); /* determine number */
extern UWORD getcols(); /* of rows and cols */
/* available */
extern LONG Enable_Abort; /* Do NOT allow abort! */
extern VOID cleanup();
/*
storage for pernament real estate...
*/
static char scrtitle[81];
static char scrn_tmp[AMG_MAXBUF+1];
static LONG scrn_tmp_p = 0L;
#endif
#if ST520
#include <osbind.h>
int STscancode = 0;
#endif
#if VMS
#include <stsdef.h>
#include <ssdef.h>
#include <descrip.h>
#include <iodef.h>
#include <ttdef.h>
#include <tt2def.h>
#define NIBUF 128 /* Input buffer size */
#define NOBUF 1024 /* MM says bug buffers win! */
#define EFN 0 /* Event flag */
char obuf[NOBUF]; /* Output buffer */
int nobuf; /* # of bytes in above */
char ibuf[NIBUF]; /* Input buffer */
int nibuf; /* # of bytes in above */
int ibufi; /* Read index */
int oldmode[3]; /* Old TTY mode bits */
int newmode[3]; /* New TTY mode bits */
short iochan; /* TTY I/O channel */
#endif
#if CPM
#include <bdos.h>
#endif
#if MSDOS & (LATTICE | MSC | AZTEC | MWC86)
union REGS rg; /* cpu register for use of DOS calls */
int nxtchar = -1; /* character held from type ahead */
#endif
#if RAINBOW
#include "rainbow.h"
#endif
#if USG /* System V */
#include <signal.h>
#include <termio.h>
struct termio otermio; /* original terminal characteristics */
struct termio ntermio; /* charactoristics to use inside */
#endif
#if V7 | BSD
#undef CTRL
#include <sgtty.h> /* for stty/gtty functions */
#include <signal.h>
struct sgttyb ostate; /* saved tty state */
struct sgttyb nstate; /* values for editor mode */
struct tchars otchars; /* Saved terminal special character set */
struct tchars ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
/* A lot of nothing */
#if BSD
#include <sys/ioctl.h> /* to get at the typeahead */
extern int rtfrmshell(); /* return from suspended shell */
#define TBUFSIZ 128
char tobuf[TBUFSIZ]; /* terminal output buffer */
#endif
#endif
/*
* This function is called once to set up the terminal device streams.
* On VMS, it translates TT until it finds the terminal, then assigns
* a channel to it and sets it raw. On CPM it is a no-op.
*/
ttopen()
{
#if AMIGA
register struct ConUnit *conunit;
register UWORD count;
struct Process *myproc;
UWORD rows,cols;
Enable_Abort = 0L; /* Disable ^C */
GfxBase = (struct GfxBase *)
OpenLibrary("graphics.library", (LONG) 0);
if (!GfxBase) /* Graphics lib */
cleanup();
IntuitionBase = (struct IntuitionBase *) /* Intuition */
OpenLibrary("intuition.library", (LONG) 0);
if (!IntuitionBase)
cleanup();
strcpy(scrtitle,"MicroEMACS ");
strcat(scrtitle,VERSION);
EmacsWindow = InitWindow(-1,0,0,0,scrtitle);
if (!EmacsWindow)
cleanup();
/* Port for reading and writing */
consoleport = CreatePort("emacs.con.port",0L);
if (!consoleport)
cleanup();
consoleWriteMsg = CreateStdIO(consoleport);
if (!consoleWriteMsg)
cleanup();
consoleReadMsg = CreateStdIO(consoleport);
if (!consoleReadMsg)
cleanup();
/* attach the console device to our window */
if ((OpenConsole(consoleWriteMsg,consoleReadMsg,EmacsWindow)))
cleanup();
/* Make AmigaDOS requesters appear in our screen */
/* "cleanup()" will restore previous value */
myproc = (struct Process *) FindTask(0L);
Forbid();
savewindow = (struct Window *) myproc->pr_WindowPtr;
myproc->pr_WindowPtr = (APTR) EmacsWindow;
Permit();
/* Set-up window size for EMACS and console.device... */
conunit = (struct ConUnit *) consoleReadMsg->io_Unit;
rows = getrows(conunit->cu_Window,conunit->cu_Font);
cols = getcols(conunit->cu_Window,conunit->cu_Font);
term.t_mrow = term.t_nrow = rows-1;
term.t_mcol = term.t_ncol = cols;
newsize(TRUE, rows );
newwidth(TRUE, cols );
/* set top offset */
ttputc(CSI);
ttputc('0');
ttputc('y');
/* set page length */
ttputc(CSI);
ttputstr(itoa( rows ));
ttputc('t');
/* set left offset */
ttputc(CSI);
ttputc('0');
ttputc('x');
/* set line length */
ttputc(CSI);
ttputstr(itoa( cols ));
ttputc('u');
/* clear screen */
ttputc(0x0c);
/* flush output buffer */
ttflush();
#endif
#if VMS
struct dsc$descriptor idsc;
struct dsc$descriptor odsc;
char oname[40];
int iosb[2];
int status;
odsc.dsc$a_pointer = "TT";
odsc.dsc$w_length = strlen(odsc.dsc$a_pointer);
odsc.dsc$b_dtype = DSC$K_DTYPE_T;
odsc.dsc$b_class = DSC$K_CLASS_S;
idsc.dsc$b_dtype = DSC$K_DTYPE_T;
idsc.dsc$b_class = DSC$K_CLASS_S;
do {
idsc.dsc$a_pointer = odsc.dsc$a_pointer;
idsc.dsc$w_length = odsc.dsc$w_length;
odsc.dsc$a_pointer = &oname[0];
odsc.dsc$w_length = sizeof(oname);
status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
exit(status);
if (oname[0] == 0x1B) {
odsc.dsc$a_pointer += 4;
odsc.dsc$w_length -= 4;
}
} while (status == SS$_NORMAL);
status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
if (status != SS$_NORMAL)
exit(status);
status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
oldmode, sizeof(oldmode), 0, 0, 0, 0);
if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
exit(status);
newmode[0] = oldmode[0];
newmode[1] = oldmode[1] | TT$M_NOECHO;
newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC);
newmode[2] = oldmode[2] | TT2$M_PASTHRU;
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
newmode, sizeof(newmode), 0, 0, 0, 0);
if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
exit(status);
term.t_nrow = (newmode[1]>>24) - 1;
term.t_ncol = newmode[0]>>16;
#endif
#if CPM
#endif
#if MSDOS & (HP150 == 0) & LATTICE
/* kill the ctrl-break interupt */
rg.h.ah = 0x33; /* control-break check dos call */
rg.h.al = 1; /* set the current state */
rg.h.dl = 0; /* set it OFF */
intdos(&rg, &rg); /* go for it! */
#endif
#if USG
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] = 0;
ioctl(0, TCSETA, &ntermio); /* and activate them */
#endif
#if V7 | BSD
gtty(0, &ostate); /* save old state */
gtty(0, &nstate); /* get base of new state */
nstate.sg_flags |= RAW;
nstate.sg_flags &= ~(ECHO|CRMOD); /* no echo for now... */
stty(0, &nstate); /* set mode */
ioctl(0, TIOCGETC, &otchars); /* Save old characters */
ioctl(0, TIOCSETC, &ntchars); /* Place new character into K */
#if BSD
/* provide a smaller terminal output buffer so that
the type ahead detection works better (more often) */
setbuffer(stdout, &tobuf[0], TBUFSIZ);
signal(SIGTSTP,SIG_DFL); /* set signals so that we can */
signal(SIGCONT,rtfrmshell); /* suspend & restart emacs */
#endif
#endif
/* on all screens we are not sure of the initial position
of the cursor */
ttrow = 999;
ttcol = 999;
}
/*
* This function gets called just before we go back home to the command
* interpreter. On VMS it puts the terminal back in a reasonable state.
* Another no-operation on CPM.
*/
ttclose()
{
#if AMIGA
amg_flush();
cleanup();
#endif
#if VMS
int status;
int iosb[1];
ttflush();
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
oldmode, sizeof(oldmode), 0, 0, 0, 0);
if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
exit(status);
status = SYS$DASSGN(iochan);
if (status != SS$_NORMAL)
exit(status);
#endif
#if CPM
#endif
#if MSDOS & (HP150 == 0) & LATTICE
/* restore the ctrl-break interupt */
rg.h.ah = 0x33; /* control-break check dos call */
rg.h.al = 1; /* set the current state */
rg.h.dl = 1; /* set it ON */
intdos(&rg, &rg); /* go for it! */
#endif
#if USG
ioctl(0, TCSETA, &otermio); /* restore terminal settings */
#endif
#if V7 | BSD
stty(0, &ostate);
ioctl(0, TIOCSETC, &otchars); /* Place old character into K */
#endif
}
/*
* Write a character to the display. On VMS, terminal output is buffered, and
* we just put the characters in the big array, after checking for overflow.
* On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
* MS-DOS (use the very very raw console output routine).
*/
ttputc(c)
#if AMIGA | ST520
char c;
#endif
{
#if AMIGA
scrn_tmp[scrn_tmp_p++] = c;
if(scrn_tmp_p >= AMG_MAXBUF)
amg_flush();
#endif
#if ST520
Bconout(2,c);
#endif
#if VMS
if (nobuf >= NOBUF)
ttflush();
obuf[nobuf++] = c;
#endif
#if CPM
bios(BCONOUT, c, 0);
#endif
#if MSDOS & MWC86
putcnb(c);
#endif
#if MSDOS & (LATTICE | AZTEC) & ~IBMPC
bdos(6, c, 0);
#endif
#if RAINBOW
Put_Char(c); /* fast video */
#endif
#if V7 | USG | BSD
fputc(c, stdout);
#endif
}
#if AMIGA
amg_flush()
{
/* speed up screen writes by turning off the cursor */
if(scrn_tmp_p)
{
CursorOff(consoleWriteMsg);
ConWrite(consoleWriteMsg,scrn_tmp,scrn_tmp_p);
CursorOn(consoleWriteMsg);
}
scrn_tmp_p = 0L;
}
ttputstr(a_str)
char *a_str;
{
while(*a_str) ttputc(*a_str++);
}
#endif
/*
* Flush terminal buffer. Does real work where the terminal output is buffered
* up. A no-operation on systems where byte at a time terminal I/O is done.
*/
ttflush()
{
#if AMIGA
amg_flush();
#endif
#if VMS
int status;
int iosb[2];
status = SS$_NORMAL;
if (nobuf != 0) {
status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
if (status == SS$_NORMAL)
status = iosb[0] & 0xFFFF;
nobuf = 0;
}
return (status);
#endif
#if CPM
#endif
#if MSDOS
#endif
#if V7 | USG | BSD
fflush(stdout);
#endif
}
/*
* Read a character from the terminal, performing no editing and doing no echo
* at all. More complex in VMS that almost anyplace else, which figures. Very
* simple on CPM, because the system can do exactly what you want.
*/
ttgetc()
{
#if AMIGA
char ch;
amg_flush();
GetChar(consoleReadMsg,&ch);
return( 255 & (int) ch);
#endif
#if ST520
long ch;
/*
* blink the cursor only if nothing is happening, this keeps the
* cursor on steadily during movement making it easier to track
*/
STcurblink(TRUE); /* the cursor blinks while we wait */
ch = Bconin(2);
STcurblink(FALSE); /* the cursor is steady while we work */
STscancode = (ch >> 16) & 0xff;
return(255 & (int)ch);
#endif
#if VMS
int status;
int iosb[2];
int term[2];
while (ibufi >= nibuf) {
ibufi = 0;
term[0] = 0;
term[1] = 0;
status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
if (status != SS$_NORMAL)
exit(status);
status = iosb[0] & 0xFFFF;
if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
exit(status);
nibuf = (iosb[0]>>16) + (iosb[1]>>16);
if (nibuf == 0) {
status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
if (status != SS$_NORMAL
|| (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
exit(status);
nibuf = (iosb[0]>>16) + (iosb[1]>>16);
}
}
return (ibuf[ibufi++] & 0xFF); /* Allow multinational */
#endif
#if CPM
return (biosb(BCONIN, 0, 0));
#endif
#if RAINBOW
int Ch;
while ((Ch = Read_Keyboard()) < 0);
if ((Ch & Function_Key) == 0)
if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177))
Ch &= 0xFF;
return Ch;
#endif
#if MSDOS & MWC86
return (getcnb());
#endif
#if MSDOS & (LATTICE | MSC | AZTEC)
int c; /* character read */
/* if a char already is ready, return it */
if (nxtchar >= 0) {
c = nxtchar;
nxtchar = -1;
return(c);
}
/* call the dos to get a char */
rg.h.ah = 7; /* dos Direct Console Input call */
intdos(&rg, &rg);
c = rg.h.al; /* grab the char */
return(c & 255);
#endif
#if V7 | USG | BSD
return(127 & fgetc(stdin));
#endif
}
#if TYPEAH
/* typahead: Check to see if any characters are already in the
keyboard buffer
*/
typahead()
{
#if MSDOS & (LATTICE | AZTEC | MWC86)
int c; /* character read */
int flags; /* cpu flags from dos call */
#if MSC
if (kbhit() != 0)
return(TRUE);
else
return(FALSE);
#endif
if (nxtchar >= 0)
return(TRUE);
rg.h.ah = 6; /* Direct Console I/O call */
rg.h.dl = 255; /* does console input */
#if LATTICE | AZTEC
flags = intdos(&rg, &rg);
#else
intcall(&rg, &rg, 0x21);
flags = rg.x.flags;
#endif
c = rg.h.al; /* grab the character */
/* no character pending */
if ((flags & 64) != 0)
return(FALSE);
/* save the character and return true */
nxtchar = c;
return(TRUE);
#endif
#if BSD
int x; /* holds # of pending chars */
return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
#endif
return(FALSE);
}
#endif