/* * txInput.c -- * * Handles 'stdin' and terminal driver settings. * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #ifndef lint static char rcsid[]="$Header: /ufs/repository/magic/textio/txInput.c,v 1.11 2001/08/23 13:48:57 tim Exp $"; #endif not lint #include #include #include #include #include #include #ifdef SYSV #include #endif #include "misc/magsgtty.h" #include "misc/magic.h" #include "misc/magsgtty.h" #include "textio/textio.h" #include "utils/geometry.h" #include "textio/txcommands.h" #include "textio/textioInt.h" #include "utils/dqueue.h" #include "graphics/graphics.h" #include "macros/macros.h" #include "utils/hash.h" #include "tiles/tile.h" #include "database/database.h" #include "database/databaseInt.h" #include "cif/CIFint.h" #include "cif/CIFread.h" #ifdef USE_READLINE #ifdef HAVE_READLINE #include #include #else #include "readline/readline.h" #include "readline/history.h" #endif #ifdef READLINE_4_DOT_2_PLUS #define filename_completion_function rl_filename_completion_function #define username_completion_function rl_username_completion_function #endif int TxPrefix(void); /* Globally keep track of the imacro string, if any; */ /* the readline callback takes no parameters. */ char *_rl_prefix; /* Custom completer function */ char **magic_completion_function(char *, int, int); /* match generators */ char *list_completion_function(char *, int); char *macro_completion_function(char *, int); char *cellname_completion_function(char *, int); char *istyle_completion_function(char *, int); char *ostyle_completion_function(char *, int); /* match list generators */ void make_techtype_list(void); void update_cellname_hash(void); char **completion_list; char **magic_command_list = (char **)NULL; char **magic_techtype_list = (char **)NULL; HashTable cellname_hash; static int interactive_flag; char *magic_direction_list[] = { "bottom", "down", "e", "east", "left", "n", "north", "right", "s", "south", "top", "up", "w", "west", (char *)NULL }; #define COMMAND_COMPL 0 #define MACRO_COMPL 1 #define IMACRO_COMPL 2 #define LAYER_COMPL 3 #define PLANE_COMPL 4 #define FILE_COMPL 5 #define CELL_COMPL 6 #define ARGS_COMPL 7 #define ISTYLE_COMPL 8 #define OSTYLE_COMPL 9 #define DIRECT_COMPL 10 /* Can only accomodate 32 arg options, increase as necessary */ static struct cmd_spec { char *cmd; int type; char *args[32]; } magic_cmd_spec[] = { { "", COMMAND_COMPL, {(char *)NULL} }, { "help", COMMAND_COMPL, {(char *)NULL} }, { "shell", FILE_COMPL, {(char *)NULL} }, { "addpath", FILE_COMPL, {(char *)NULL} }, { "path", FILE_COMPL, {(char *)NULL} }, { "logcommands", FILE_COMPL, {(char *)NULL} }, { "startrsim", FILE_COMPL, {(char *)NULL} }, { "rsim", FILE_COMPL, {(char *)NULL} }, { "source", FILE_COMPL, {(char *)NULL} }, { "save", FILE_COMPL, {(char *)NULL} }, { "getcell", CELL_COMPL, {(char *)NULL} }, { "child", CELL_COMPL, {(char *)NULL} }, { "parent", CELL_COMPL, {(char *)NULL} }, { "dump", CELL_COMPL, {(char *)NULL} }, { "list", CELL_COMPL, {(char *)NULL} }, { "load", CELL_COMPL, {(char *)NULL} }, { "xload", CELL_COMPL, {(char *)NULL} }, { "macro", MACRO_COMPL, {(char *)NULL} }, { "imacro", IMACRO_COMPL, {(char *)NULL} }, { "see*", LAYER_COMPL, {(char *)NULL} }, { "paint", LAYER_COMPL, {(char *)NULL} }, { "*extract", ARGS_COMPL, {"clrdebug", "clrlength", "driver", "interactions", "intercount", "parents", "receiver", "setdebug", "showdebug", "showparents", "showtech", "stats", "step", "times", (char *)NULL} }, { "*garoute", ARGS_COMPL, {"clrdebug", "setdebug", "showdebug", (char *)NULL} }, { "*groute", ARGS_COMPL, {"clrdebug", "onlynet", "setdebug", "showdebug", "sides", (char *)NULL} }, { "*iroute", ARGS_COMPL, {"debug", "help", "parms", (char *)NULL} }, { "*malloc", ARGS_COMPL, {"all", "off", "on", "only", "watch", "unwatch", (char *)NULL} }, { "*mzroute", ARGS_COMPL, {"debug", "dumpEstimates", "dumpTags", "help", "numberLine", "parms", "plane", "version", (char *)NULL} }, { "*plow", ARGS_COMPL, {"help", "clrdebug", "jogreduce", "lwidth", "lshadow", "mergedown", "mergeup", "move", "outline", "plow", "print", "random", "setdebug", "shadow", "showdebug", "split", "techshow", "trail", "whenbot", "whentop", "width", (char *)NULL} }, { "*plow lwidth", LAYER_COMPL, { (char *)NULL } }, { "*plow width", LAYER_COMPL, { (char *)NULL } }, { "*plow lshadow", LAYER_COMPL, { (char *)NULL } }, { "*plow shadow", LAYER_COMPL, { (char *)NULL } }, { "*plow techshow", FILE_COMPL, { (char *)NULL } }, { "*plow outline", DIRECT_COMPL, { (char *)NULL } }, { "*plow plow", DIRECT_COMPL, { (char *)NULL } }, { "*profile", ARGS_COMPL, {"on", "off", (char *)NULL} }, { "*watch", PLANE_COMPL, {(char *)NULL} }, { "*watch*", ARGS_COMPL, {"demo", "types", (char *)NULL} }, { "calma", ARGS_COMPL, {"help", "flatten", "labels", "lower", "noflatten", "nolabels", "nolower", "read", "write", (char *)NULL} }, { "calma read", FILE_COMPL, { (char *)NULL } }, { "calma write", FILE_COMPL, { (char *)NULL } }, { "cif", ARGS_COMPL, {"help", "arealabels", "idcell", "istyle", "prefix", "ostyle", "read", "see", "statistics", "write", "flat", (char *)NULL} }, { "cif read", FILE_COMPL, { (char *)NULL } }, { "cif flat", FILE_COMPL, { (char *)NULL } }, { "cif write", FILE_COMPL, { (char *)NULL } }, { "cif idcell", ARGS_COMPL, { "yes", "no", (char *)NULL } }, { "cif arealabels", ARGS_COMPL, { "yes", "no", (char *)NULL } }, { "cif prefix", FILE_COMPL, { (char *)NULL } }, { "cif see", LAYER_COMPL, { (char *)NULL } }, { "cif istyle", ISTYLE_COMPL, { (char *)NULL } }, { "cif ostyle", OSTYLE_COMPL, { (char *)NULL } }, { "copy", DIRECT_COMPL, { (char *)NULL } }, { "move", DIRECT_COMPL, { (char *)NULL } }, { "stretch", DIRECT_COMPL, { (char *)NULL } }, { "drc", ARGS_COMPL, {"help", "catchup", "check", "count", "find", "off", "on", "printrules", "rulestats", "statistics", "why", (char *)NULL} }, { "drc printrules", FILE_COMPL, { (char *)NULL } }, { "ext", ARGS_COMPL, {"help", "all", "cell", "do", "length", "no", "parents", "showparents", "style", "unique", "warn", (char *)NULL} }, { "ext style", OSTYLE_COMPL, { (char *)NULL } }, { "feedback", ARGS_COMPL, {"help", "add", "clear", "count", "find", "save", "why", "fill", (char *)NULL} }, { "feedback save", FILE_COMPL, { (char *)NULL } }, { "garoute", ARGS_COMPL, {"help", "channel", "generate", "nowarn", "route", "reset", "warn", (char *)NULL} }, { "getnode", ARGS_COMPL, {"alias", "fast", "abort", (char *)NULL} }, { "iroute", ARGS_COMPL, {"help", "contacts", "layers", "route", "saveParameters", "search", "spacings", "verbosity", "version", "wizard", (char *)NULL} }, { "iroute help", ARGS_COMPL, {"contacts", "layers", "route", "saveParameters", "search", "spacings", "verbosity", "version", "wizard", (char *)NULL} }, { "plot", ARGS_COMPL, {"help", "postscript", "gremlin", "versatec", "pnm", "parameters", (char *)NULL} }, { "plot postscript", FILE_COMPL, { (char *)NULL } }, { "plot gremlin", FILE_COMPL, { (char *)NULL } }, { "plot versatec", FILE_COMPL, { (char *)NULL } }, { "plot pnm", FILE_COMPL, { (char *)NULL } }, { "plow", ARGS_COMPL, {"help", "boundary", "horizon", "jogs", "selection", "straighten", "noboundary", "nojogs", "nostraighten", (char *)NULL} }, { "plow selection", DIRECT_COMPL, { (char *)NULL } }, { "route", ARGS_COMPL, {"help", "end", "jog", "metal", "netlist", "obstacle", "origin", "stats", "settings", "steady", "tech", "vias", "viamin", (char *)NULL} }, { "route netlist", FILE_COMPL, { (char *)NULL } }, { "select", ARGS_COMPL, {"help", "more", "less", "area", "visible", "cell", "clear", "save", "box", (char *)NULL} }, { "select save", FILE_COMPL, { (char *)NULL } }, { "select more", ARGS_COMPL, { "area", "visible", "cell", "box", (char *)NULL } }, { "select less", ARGS_COMPL, { "area", "visible", "cell", "box", (char *)NULL } }, { "select more area", LAYER_COMPL, { (char *)NULL } }, { "select less area", LAYER_COMPL, { (char *)NULL } }, { "select more visible", LAYER_COMPL, { (char *)NULL } }, { "select less visible", LAYER_COMPL, { (char *)NULL } }, { "select more cell", CELL_COMPL, { (char *)NULL } }, { "select less cell", CELL_COMPL, { (char *)NULL } }, { "select more box", LAYER_COMPL, { (char *)NULL } }, { "select less box", LAYER_COMPL, { (char *)NULL } }, { "send", ARGS_COMPL, {"netlist", "color", "layout", (char *)NULL} }, { "snap", ARGS_COMPL, {"on", "off", (char *)NULL} }, { "tool", ARGS_COMPL, {"box", "wiring", "netlist", "rsim", (char *)NULL} }, { "wire", ARGS_COMPL, {"help", "horizontal", "leg", "switch", "type", "vertical", (char *)NULL} }, { "wire type", LAYER_COMPL, { (char *)NULL } }, { "wire switch", LAYER_COMPL, { (char *)NULL } }, { "history", ARGS_COMPL, {"n", "r", "help", (char *)NULL} }, { (char *)NULL , 0, {(char *)NULL} } }; #endif /* Characters for input processing. Set to -1 if not defined */ char *TxGetLinePfix(); char txEraseChar = -1; /* Erase line (e.g. ^H) */ char txKillChar = -1; /* Kill line (e.g. ^U or ^X) */ char txWordChar = -1; /* Erase a word (e.g. ^W) */ char txReprintChar = -1; /* Reprint the line (e.g. ^R */ char txLitChar = -1; /* Literal next character (e.g. ^V */ char txBreakChar = -1; /* Break to a new line (normally -1) */ char TxEOFChar = -1; /* The current EOF character (e.g. ^D) */ char TxInterruptChar = -1; /* The current interrupt character (e.g. ^C) */ static char txPromptChar; /* the current prompt */ bool txHavePrompt = FALSE; /* is a prompt on the screen? */ char *txReprint1 = NULL; char *txReprint2 = NULL; /* * ---------------------------------------------------------------------------- * * TxReprint -- * * Reprint the current input line. Used for ^R and after ^Z. * * Results: * None. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ void TxReprint() { (void) txFprintfBasic(stdout, "\n"); if (txReprint1 != NULL) (void) txFprintfBasic(stdout, "%s", txReprint1); if (txReprint2 != NULL) (void) txFprintfBasic(stdout, "%s", txReprint2); (void) fflush(stdout); } /* * ---------------------------------------------------------------------------- * TxSetPrompt -- * * Set the current prompt. * * Results: * None. * * Side effects: * You can guess. * ---------------------------------------------------------------------------- */ void TxSetPrompt(ch) char ch; { txPromptChar = ch; } /* * ---------------------------------------------------------------------------- * TxPrompt -- * * Put up the prompt which was set by TxSetPrompt. * * Results: * None. * * Side effects: * You can guess. * ---------------------------------------------------------------------------- */ void TxPrompt() { static char lastPromptChar; static char prompts[2]; if (txHavePrompt && (lastPromptChar == txPromptChar)) return; (void) fflush(stderr); if (txHavePrompt) TxUnPrompt(); if (TxInteractive) txFprintfBasic(stdout, "%c", txPromptChar); (void) fflush(stdout); prompts[0] = txPromptChar; prompts[1] = '\0'; txReprint1 = prompts; txHavePrompt = TRUE; lastPromptChar = txPromptChar; } /* * ---------------------------------------------------------------------------- * TxRestorePrompt -- * * The prompt was erased for some reason. Restore it. * * Results: * None. * * Side effects: * You can guess. * ---------------------------------------------------------------------------- */ void TxRestorePrompt() { if (txHavePrompt) { txHavePrompt = FALSE; TxPrompt(); } } /* * ---------------------------------------------------------------------------- * TxUnPrompt -- * * Erase the prompt. * * Results: * None. * * Side effects: * You can guess. * ---------------------------------------------------------------------------- */ void TxUnPrompt() { if (txHavePrompt) { (void) fflush(stderr); if (TxInteractive) fputs("\b \b", stdout); (void) fflush(stdout); txReprint1 = NULL; txHavePrompt = FALSE; } } /* * ---------------------------------------------------------------------------- * * TxGetChar -- * * Get a single character from the input stream (terminal or whatever). * * Results: * One character, or EOF. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ int TxGetChar() { int ch; extern DQueue txInputEvents, txFreeEvents; extern TxInputEvent txLastEvent; TxInputEvent *event; while (TRUE) { /* Get an input character. Don't let TxGetInputEvent return * because of a SigWinch or whatever. It would be nice to process * SigWinches in a middle of text input, but that is difficult * to do since SigWinches are processed in the normal * command-interpretation process. Thus, we delay the processing * until after the text is collected. */ if (DQIsEmpty(&txInputEvents)) TxGetInputEvent(TRUE, FALSE); event = (TxInputEvent *) DQPopFront(&txInputEvents); ASSERT(event != NULL, "TxGetChar"); txLastEvent = *event; if (event->txe_button == TX_EOF) { ch = EOF; goto gotone; } if (event->txe_button == TX_CHARACTER) { ch = TranslateChar(event->txe_ch); goto gotone; } DQPushRear(&txFreeEvents, (ClientData) event); } gotone: DQPushRear(&txFreeEvents, (ClientData) event); return ch; } #ifdef USE_READLINE #undef free /* * ---------------------------------------------------------------------------- * TxPrefix -- * Instantiation of the readline function *rl_pre_input_hook(), executed * between the prompt and the input (readline v4.1). Prepends the text * of an interactive macro (if non-NULL) to the command line. * * ---------------------------------------------------------------------------- */ int TxPrefix(void) { if (_rl_prefix != NULL) rl_insert_text(_rl_prefix); rl_redisplay(); } char ** magic_completion_function(char *text, int start, int end) { CPFunction *completion_func = (CPFunction *)NULL; char **matches, **tokens; char *line = strdup(rl_line_buffer); int i; for(i=start; i>=0; i--) { if( isspace(line[i]) || line[i] == ';' ) { break; } } line[i+1] = '\0'; if( (tokens=history_tokenize(line)) != NULL ) { int entry, start_token, num_tokens; num_tokens = 0; while( tokens[num_tokens] != (char *)NULL ) { num_tokens++; } for(start_token=num_tokens-1; start_token>=0; start_token--) { if( tokens[start_token][0] == ';' ) { break; } } start_token++; line[0] = '\0'; for(i=start_token; i= 1 ) { sprintf(line, "%s*", tokens[0]); entry = LookupStructFull(line, (char **)&magic_cmd_spec, sizeof(struct cmd_spec)); } if( entry >= 0 ) { switch( magic_cmd_spec[entry].type ) { case COMMAND_COMPL: completion_func = list_completion_function; completion_list = magic_command_list; break; case MACRO_COMPL: completion_func = macro_completion_function; interactive_flag = 0; break; case IMACRO_COMPL: completion_func = macro_completion_function; interactive_flag = 1; break; case LAYER_COMPL: completion_func = list_completion_function; if( magic_techtype_list == (char **)NULL ) { make_techtype_list(); } completion_list = magic_techtype_list; break; case PLANE_COMPL: completion_func = list_completion_function; completion_list = DBPlaneLongNameTbl; break; case FILE_COMPL: completion_func = (text[0] == '~') ? username_completion_function : filename_completion_function; break; case CELL_COMPL: update_cellname_hash(); completion_func = cellname_completion_function; break; case ARGS_COMPL: completion_func = list_completion_function; completion_list = magic_cmd_spec[entry].args; break; case ISTYLE_COMPL: completion_func = istyle_completion_function; break; case OSTYLE_COMPL: completion_func = ostyle_completion_function; break; case DIRECT_COMPL: completion_func = list_completion_function; completion_list = magic_direction_list; break; } } for(i=0; id_name, DBSuffix)) != (char *)NULL && base[strlen(DBSuffix)] == '\0' ) { *base = '\0'; HashFind(&cellname_hash, dirent->d_name); } } closedir(dir); } } free(dirname); } char * istyle_completion_function(char *text, int state) { extern CIFReadStyle *cifReadStyleList; static CIFReadStyle *style; static int len; if( state == 0 ) { style = cifReadStyleList; len = strlen(text); } for(; style!=NULL; style=style->crs_next) { if( strncmp(style->crs_name, text, len) == 0 ) { char *name = style->crs_name; style = style->crs_next; return strdup(name); } } return (char *)NULL; } char * ostyle_completion_function(char *text, int state) { extern CIFStyle *CIFStyleList; static CIFStyle *style; static int len; if( state == 0 ) { style = CIFStyleList; len = strlen(text); } for(; style!=NULL; style=style->cs_next) { if( strncmp(style->cs_name, text, len) == 0 ) { char *name = style->cs_name; style = style->cs_next; return strdup(name); } } return (char *)NULL; } char * cellname_completion_function(char *text, int state) { extern HashTable dbCellDefTable; static int len; static HashSearch hs, db_hs; HashEntry *he; if( state == 0 ) { len = strlen(text); HashStartSearch(&hs); HashStartSearch(&db_hs); } while( (he = HashNext(&cellname_hash, &hs)) != (HashEntry *)NULL ) { if( strncmp(he->h_key.h_name, text, len) == 0 ) { return strdup(he->h_key.h_name); } } /* Also complete cells that are in main memory only */ while( (he = HashNext(&dbCellDefTable, &db_hs)) != (HashEntry *)NULL ) { CellDef *cd = (CellDef *)HashGetValue(he); if( !(cd->cd_flags & CDINTERNAL) && strcmp(cd->cd_name, UNNAMED) != 0 && strncmp(cd->cd_name, text, len) == 0 ) { return strdup(cd->cd_name); } } return (char *)NULL; } char * macro_completion_function(char *text, int state) { static macrodef *macro; static int len; if( state == 0 ) { macro = mactable; len = strlen(text); } while( macro != NULL ) { if( (macro->interactive == TRUE && interactive_flag == 1) || (macro->interactive == FALSE && interactive_flag == 0) ) { char *macro_name = MacroName(macro->keyvalue); if (strncmp(macro_name, text, len) == 0 ) { macro = macro->nextmacro; return strdup(macro_name); } } macro = macro->nextmacro; } return (char *)NULL; } char * list_completion_function(char *text, int state) { static int list_index, len; char *match; /* If this is a new word to complete, initialize now. This includes saving the length of TEXT for efficiency, and initializing the index variable to 0. */ if( state == 0 ) { list_index = 0; len = strlen(text); } /* Return the next name which partially matches from the command list. */ while( (match = completion_list[list_index]) != (char *)NULL ) { list_index++; if( strncmp(match, text, len) == 0 ) { return strdup(match); } } return (char *)NULL; } void make_techtype_list(void) { int i, techdep_layers = DBNumUserLayers - TT_TECHDEPBASE; magic_techtype_list = (char **)mallocMagic(sizeof(char *)*(techdep_layers+8+2+1)); for(i=0; i= maxChars) { TxPrintf ("WARNING: input string too long; truncated"); res[maxChars-1] = '\0'; } if( return_nothing ) { dest[0] = '\0'; } else { strcpy (dest, res); } #undef free free (res); if( hist_res != (char *)NULL ) free(hist_res); #define free You_should_use_the_Magic_procedure_freeMagic res = dest; } TxSetTerminal (); #endif return res; } /* * ---------------------------------------------------------------------------- */ char * TxGetLinePrompt(dest, maxChars, prompt) char *dest; int maxChars; char *prompt; { return TxGetLineWPrompt(dest, maxChars, prompt, NULL); } /* * ---------------------------------------------------------------------------- * TxGetLinePfix: * * Reads a line from the input queue (terminal or whatever). * * Results: * A char pointer to the string is returned. * If an end-of-file is typed, returns (char *) NULL and * stores in the string any characters recieved up to that point. * * Side effects: * The input stream is read, and 'dest' is filled in with up to maxChars-1 * characters. Up to maxChars of the 'dest' may be changed during the * input process, however, since a '\0' is added at the end. There is no * newline at the end of 'dest'. * ---------------------------------------------------------------------------- */ char * TxGetLinePfix(dest, maxChars, prefix) char *dest; int maxChars; char *prefix; { int i; char *ret; int ch; bool literal; if (maxChars < 1) return dest; if (txHavePrompt) TxUnPrompt(); ret = dest; dest[0] = '\0'; txReprint2 = dest; #define TX_ERASE() ( (i>0) ?(i--, fputs("\b \b", stdout), 0) :0) (void) fflush(stderr); literal = FALSE; i = 0; if (prefix != NULL) { while (prefix[i] != '\0') { if (i >= maxChars - 1) break; dest[i] = prefix[i]; txFprintfBasic(stdout, "%c", prefix[i]); i++; } } while (TRUE) { dest[i] = '\0'; if (i >= maxChars - 1) break; (void) fflush(stdout); ch = TxGetChar(); if (ch == EOF || ch == -1 || ch == TxEOFChar) { TxError("\nEOF encountered on input stream.\n"); ret = NULL; break; } else if (literal) { literal = FALSE; dest[i] = ch; txFprintfBasic(stdout, "%c", ch); i++; } else if (ch == '\n' || ch == txBreakChar) { break; } else if (ch == '\t') { while (TRUE) { dest[i] = ' '; txFprintfBasic(stdout, " "); i++; if (((i + strlen(txReprint1)) % 8) == 0) break; } } else if (ch == txEraseChar) { TX_ERASE(); } else if (ch == txKillChar) { while (i > 0) TX_ERASE(); } else if (ch == txWordChar) { while (i > 0 && isspace(dest[i-1])) TX_ERASE(); while (i > 0 && !isspace(dest[i-1])) TX_ERASE(); } else if (ch == txReprintChar) { TxReprint(); } else if (ch == txLitChar) { literal = TRUE; } else { dest[i] = ch; txFprintfBasic(stdout, "%c", ch); i++; } } txFprintfBasic(stdout, "\n"); txHavePrompt = FALSE; txReprint2 = NULL; return ret; } /* * ---------------------------------------------------------------------------- * TxGetLine: */ char * TxGetLine(dest, maxChars) char *dest; int maxChars; { return TxGetLinePfix(dest, maxChars, NULL); } /* * ---------------------------------------------------------------------------- * txGetTermState: * * Read the state of the terminal and driver. * * Results: * none. * * Side effects: * The passed structure is filled in. * ---------------------------------------------------------------------------- */ #if defined(SYSV) || defined(CYGWIN) void txGetTermState(buf) struct termio *buf; { ioctl( fileno( stdin ), TCGETA, buf); } #else void txGetTermState(buf) txTermState *buf; { ASSERT(TxStdinIsatty, "txGetTermState"); /* save the current terminal characteristics */ (void) ioctl(fileno(stdin), TIOCGETP, (char *) &(buf->tx_i_sgtty) ); (void) ioctl(fileno(stdin), TIOCGETC, (char *) &(buf->tx_i_tchars) ); } #endif SYSV /* * ---------------------------------------------------------------------------- * txSetTermState: * * Set the state of the terminal and driver. * * Results: * none. * * Side effects: * The terminal driver is set up. * ---------------------------------------------------------------------------- */ void txSetTermState(buf) #if defined(SYSV) || defined(CYGWIN) struct termio *buf; #else txTermState *buf; #endif SYSV { #if defined(SYSV) || defined(CYGWIN) ioctl( fileno(stdin), TCSETAF, buf ); #else /* set the current terminal characteristics */ (void) ioctl(fileno(stdin), TIOCSETN, (char *) &(buf->tx_i_sgtty) ); (void) ioctl(fileno(stdin), TIOCSETC, (char *) &(buf->tx_i_tchars) ); #endif SYSV } /* * ---------------------------------------------------------------------------- * txInitTermRec: * * Sets the terminal record that it has echo turned off, * cbreak on, and no EOFs the way we like it. * * Results: * The passed terminal record is modified. * * Side effects: * No terminal modes are actually changed. * ---------------------------------------------------------------------------- */ void txInitTermRec(buf) #if defined(SYSV) || defined(CYGWIN) struct termio *buf; #else txTermState *buf; #endif SYSV { #if defined(SYSV) || defined(CYGWIN) buf->c_lflag = ISIG; /* raw: no echo and no processing, allow signals */ buf->c_cc[ VMIN ] = 1; buf->c_cc[ VTIME ] = 0; #else /* set things up for us, turn off echo, turn on cbreak, no EOF */ buf->tx_i_sgtty.sg_flags |= CBREAK; buf->tx_i_sgtty.sg_flags &= ~ECHO; buf->tx_i_tchars.t_eofc = -1; /* Give the graphics module a chance to override this. */ if (GrTermStatePtr) (*GrTermStatePtr)(&buf->tx_i_sgtty, &buf->tx_i_tchars); #endif SYSV } #if defined(SYSV) || defined(CYGWIN) struct termio closeTermState; #else static txTermState closeTermState; #endif SYSV static bool haveCloseState = FALSE; /* * ---------------------------------------------------------------------------- * txSaveTerm: * * Save the terminal characteristics so they can be restored when * magic leaves. * * * Results: * none. * * Side effects: * a global variable is set. * ---------------------------------------------------------------------------- */ void txSaveTerm() { #if defined(SYSV) || defined(CYGWIN) ioctl( fileno( stdin ), TCGETA, &closeTermState); txEraseChar = closeTermState.c_cc[VERASE]; txKillChar = closeTermState.c_cc[VKILL]; TxEOFChar = closeTermState.c_cc[VEOF]; TxInterruptChar = closeTermState.c_cc[VINTR]; haveCloseState = TRUE; #else struct ltchars lt; txGetTermState(&closeTermState); (void) ioctl(fileno(stdin), TIOCGLTC, (char *) <); txEraseChar = closeTermState.tx_i_sgtty.sg_erase; txKillChar = closeTermState.tx_i_sgtty.sg_kill; txWordChar = lt.t_werasc; txReprintChar = lt.t_rprntc; txLitChar = lt.t_lnextc; txBreakChar = closeTermState.tx_i_tchars.t_brkc; TxEOFChar = closeTermState.tx_i_tchars.t_eofc; TxInterruptChar = closeTermState.tx_i_tchars.t_intrc; haveCloseState = TRUE; #endif SYSV } /* * ---------------------------------------------------------------------------- * TxSetTerminal: * * Sets the terminal up the way we like it. * * Results: * none. * * Side effects: * The terminal modes are changed. * ---------------------------------------------------------------------------- */ void TxSetTerminal() { #if defined(SYSV) || defined(CYGWIN) struct termio buf; #else txTermState buf; #endif SYSV if (TxStdinIsatty) { if (!haveCloseState) txSaveTerm(); buf = closeTermState; txInitTermRec(&buf); txSetTermState(&buf); } } /* * ---------------------------------------------------------------------------- * TxResetTerminal: * * Returns the terminal to the way it was when Magic started up. * * Results: * none. * * Side effects: * The terminal modes are changed. * ---------------------------------------------------------------------------- */ void TxResetTerminal() { if (TxStdinIsatty && haveCloseState) txSetTermState(&closeTermState); }