/* * 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 #include #include #include #include #include "keymap.h" struct IntuitionBase *IntuitionBase; #define INTUITION_REV 29 static struct NewWindow NewWindow = { 0, 0, 640, 200, -1, -1, 0, SMART_REFRESH | ACTIVATE | WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING, NULL, NULL, "MicroEMACS", NULL, NULL, 100, 35, 640, 200, WBENCHSCREEN }; static struct Window *Window; static struct IOStdReq consoleIO; static struct MsgPort consoleMsgPort; #define NOBUF 1024 static char obuf[NOBUF]; static int nobuf; /* * This function fills in the keymap string fields */ static void FillIn(keytypes, keymap, n, strings) UBYTE *keytypes; UBYTE **keymap; int n; char **strings; { int i; for (i = 0; i < n; ++i) { if (keytypes[i] & KCF_STRING) { if (*strings == NULL) { printf("too few KeyStrings\n"); exit(1); } keymap[i] = *strings; ++strings; } } if (*strings != NULL) { printf("too many KeyStrings\n"); exit(1); } } /* * This function is called once to set up the terminal device streams. * On VMS, it translates SYS$INPUT until it finds the terminal, then assigns * a channel to it and sets it raw. On CPM it is a no-op. */ ttopen() { int i; IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", INTUITION_REV); if (IntuitionBase == NULL) { printf("can't open Intuition\n"); exit(1); } Window = (struct Window *)OpenWindow(&NewWindow); if (Window == NULL) { printf("can't open window\n"); exit(1); } consoleIO.io_Data = (APTR) Window; consoleIO.io_Length = sizeof(*Window); if (OpenDevice("console.device", 0, &consoleIO, 0) != 0) { printf("can't open console\n"); exit(1); } consoleMsgPort.mp_Node.ln_Type = NT_MSGPORT; consoleMsgPort.mp_Flags = 0; if ((i = AllocSignal(-1)) == -1) { printf("can't AllocSignal\n"); exit(1); } consoleMsgPort.mp_SigBit = i; consoleMsgPort.mp_SigTask = (struct Task *)FindTask(NULL); consoleIO.io_Message.mn_ReplyPort = &consoleMsgPort; FillIn(HiKeyMapTypes, HiKeyMap, 40, HiStrings); consoleIO.io_Command = CD_SETKEYMAP; consoleIO.io_Data = (APTR) &KeyMap; consoleIO.io_Length = sizeof(KeyMap); DoIO(&consoleIO); nobuf = 0; } /* * 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() { ttflush(); CloseDevice(&consoleIO); CloseWindow(Window); CloseLibrary(IntuitionBase); } /* * 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 (nobuf >= NOBUF) ttflush(); obuf[nobuf++] = c; } /* * 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 (nobuf != 0) { register int i = nobuf; /* The DoIO write to the console trashes D7, so we declare an unnecessary register variable here to for it to be saved */ consoleIO.io_Command = CMD_WRITE; consoleIO.io_Data = (APTR) obuf; consoleIO.io_Length = i; DoIO(&consoleIO); nobuf = 0; } } /* * 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() { char ch; consoleIO.io_Command = CMD_READ; consoleIO.io_Data = (APTR) &ch; consoleIO.io_Length = 1; DoIO(&consoleIO); return((int)ch); }