📄 lycurses.c
字号:
* Further mods by Fote. 27-Jan-1994 * Added back a typeahead() which supports 'z' or 'Z' as * an "Zap transfer" command via HTCheckForInterrupt() * in LYUtils.c. */#include <descrip.h>#include <iodef.h>#include <ssdef.h>#include <stdlib.h>#include <msgdef.h>#include <ttdef.h>#include <tt2def.h>#include <libclidef.h>#include <lib$routines.h>#include <starlet.h>#include <clidef.h>#include <syidef.h>#ifdef signal#undef signal#endif /* signal */#include <signal.h>#ifdef system#undef system#endif /* system */#include <processes.h>#include "LYVMSdef.h"#define EFN 0 /* Event flag */static unsigned char buffer[20]; /* Input buffer */static int in_pos, in_len; /* For escape sequences */static int oldmode[3]; /* Old TTY mode bits */static int newmode[3]; /* New TTY mode bits */static short iochan; /* TTY I/O channel */static $DESCRIPTOR(term_nam_dsc,"TT"); /* Descriptor for iochan */static unsigned long mask = LIB$M_CLI_CTRLY|LIB$M_CLI_CTRLT; /* ^Y and ^T */static unsigned long old_msk; /* Saved control mask */static short trap_flag = FALSE; /* TRUE if AST is set */BOOLEAN DidCleanup = FALSE; /* Exit handler flag */static char VersionVMS[20]; /* Version of VMS */PUBLIC int VMSVersion ARGS2( char *, VerString, int, VerLen){ unsigned long status, itm_cod = SYI$_VERSION; int i, verlen = 0; struct dsc$descriptor version; char *m; version.dsc$a_pointer = VerString; version.dsc$w_length = VerLen - 1; version.dsc$b_dtype = DSC$K_DTYPE_B; version.dsc$b_class = DSC$K_CLASS_S; status = lib$getsyi(&itm_cod, 0, &version, &verlen, 0, 0); if (!(status&1) || verlen == 0) return 0; /* * Cut out trailing spaces */ for (m = VerString+verlen, i = verlen-1; i > 0 && VerString[i] == ' '; --i) *(--m) = '\0'; return strlen(VerString)+1; /* Transmit ending 0 too */}PUBLIC void VMSexit NOARGS{ /* * If we get here and DidCleanup is not set, it was via an * ACCVIO, or outofmemory forced exit, so make *sure* we * attempt a cleanup and reset the terminal. */ if (!DidCleanup) { if (LYOutOfMemory == FALSE) { fprintf(stderr,"\nA Fatal error has occurred in %s Ver. %s\n", LYNX_NAME, LYNX_VERSION); fprintf(stderr,"\nPlease notify your system administrator to confirm a bug, and if\n"); fprintf(stderr,"confirmed, to notify the lynx-dev list. Bug reports should have concise\n"); fprintf(stderr,"descriptions of the command and/or URL which causes the problem, the\n"); fprintf(stderr,"operating system name with version number, the TCPIP implementation, the\n"); fprintf(stderr,"TRACEBACK if it can be captured, and any other relevant information.\n"); if (LYTraceLogFP == NULL) { fprintf(stderr,"\nPress RETURN to clean up: "); (void) getchar(); } } else if (LYCursesON) { _statusline(MEMORY_EXHAUSTED_ABORT); sleep(AlertSecs); } cleanup(); } if (LYOutOfMemory == TRUE) { printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT); fflush(stdout); fflush(stderr); }}/* * TTOPEN -- * This function is called once to set up the terminal * device streams. It translates TT until it finds * the terminal, then assigns a channel to it, sets it * to EDIT, and sets up the Ctrl-C and Ctrl-Y interrupt * handling. */PUBLIC int ttopen NOARGS{ extern void cleanup_sig(); int iosb[2]; int status; static unsigned long condition; static struct _exit_block { unsigned long forward; unsigned long address; unsigned long zero; unsigned long condition; } exit_handler_block; status = sys$assign( &term_nam_dsc, &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 ) exit( status ); status = iosb[0] & 0xFFFF; if( status != SS$_NORMAL ) exit( status ); newmode[0] = oldmode[0]; newmode[1] = oldmode[1]; newmode[2] = oldmode[2] | TT2$M_EDIT; status = sys$qiow( EFN, iochan, IO$_SETMODE, &iosb, 0, 0, &newmode, sizeof(newmode), 0, 0, 0, 0 ); if( status != SS$_NORMAL ) exit( status ); status = iosb[0] & 0xFFFF; if( status != SS$_NORMAL ) exit( status ); /* * Declare the exit handler block. */ exit_handler_block.forward = 0; exit_handler_block.address = (unsigned long) &VMSexit; exit_handler_block.zero = 0; exit_handler_block.condition = (unsigned long) &condition; status = sys$dclexh(&exit_handler_block); if (status != SS$_NORMAL) exit( status ); /* * Set the AST. */ lib$disable_ctrl(&mask, &old_msk); trap_flag = TRUE; status = sys$qiow ( EFN, iochan, IO$_SETMODE|IO$M_CTRLCAST|IO$M_CTRLYAST, &iosb, 0, 0, &cleanup_sig, SIGINT, 0, 0, 0, 0 ); if ( status != SS$_NORMAL ) { lib$enable_ctrl(&old_msk); exit ( status ); } /* * Get the version of VMS. */ if (VMSVersion(VersionVMS, 20) < 3) /* * Load zeros on error. */ strcpy(VersionVMS, "V0.0-0"); return(0);} /* ttopen *//* * TTCLOSE -- * This function gets called just before we go back home * to the command interpreter. It puts the terminal back * in a reasonable state. */PUBLIC int ttclose NOARGS{ int status; int iosb[1]; 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 ); if (trap_flag) { status = sys$dassgn (iochan); status = lib$enable_ctrl(&old_msk); trap_flag = FALSE; } return(0);} /* ttclose *//* * TTGETC -- * Read a character from the terminal, with NOECHO and NOFILTR. */PUBLIC int ttgetc NOARGS{ int status; unsigned short iosb[4]; if (in_pos < in_len) return(buffer[in_pos++]); status = sys$qiow(EFN, iochan, IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR, &iosb, 0, 0, &buffer, 1, 0, 0, 0, 0); if ((status&1) == 1) status = iosb[0]; if (status == SS$_PARTESCAPE) { /* * Escape sequence in progress. Fake a successful read. */ status = 1; } if ((status&1) != 1 && status != SS$_DATAOVERUN) exit(status); in_pos = 1; in_len = iosb[1] + iosb[3]; return(buffer[0]);}/* * TYPEAHEAD -- Fote Macrides 27-Jan-1994 * Check whether a keystroke has been entered, and return * it, or -1 if none was entered. */PUBLIC int typeahead NOARGS{ int status; unsigned short iosb[4]; if (dump_output_immediately) return -1; if (in_pos < in_len) return(buffer[in_pos++]);again: status = sys$qiow (EFN, iochan, IO$_READVBLK|IO$M_TIMED|IO$M_NOECHO|IO$M_NOFILTR, &iosb, 0, 0, &buffer, 1, 0, 0, 0, 0); if ((status&1) == 1) status = iosb[0]; if (status == SS$_PARTESCAPE) { /* * Escape sequence in progress, finish reading it. */ goto again; } in_pos = 1; in_len = iosb[1] + iosb[3]; if (status == SS$_TIMEOUT || status == SS$_DATAOVERUN) return(-1); return (buffer[0]);}/* * VMSSIGNAL -- Fote Macrides 29-Jun-1993 * Sets up AST for both Ctrl-C and Ctrl-Y, with system response * to Ctrl-T disabled. If called with a sig other than SIGINT, * it will use the C library's system(sig, func). * The equivalent of VMSsignal(SIGINT, cleanup_sig) is done on * intialization by ttopen(), so don't do it again. * VMSsignal(SIGINT, SIG_DFL) is treated as a call to ttclose(). * Call VMSsignal(SIGINT, SIG_IGN) before system() calls to * enable Ctrl-C and Ctrl-Y in the subprocess, and then call * VMSsignal(SIG_INT, cleanup_sig) on return from the subprocess. * For func's which set flags and do not invoke an exit from * LYNX, the func should reassert itself. * The VMS signal() calls do not fully emulate the Unix calls, * and VMSsignal() is just a "helper", also not a full emulation. */PUBLIC void *VMSsignal (sig,func)int sig;void (*func)();{ int status; short iosb[4]; static int SIG_IGN_flag; /* * Pass all signals other than SIGINT to signal(). * Also pass SIGINT to signal() if we're dumping. */ if (sig != SIGINT || dump_output_immediately) { signal(sig, func); return; } /* * If func is SIG_DFL, treat it as ttclose(). */ if (func == SIG_DFL) { ttclose(); return; } /* * Clear any previous AST. */ if (trap_flag) { status = sys$dassgn (iochan); status = lib$enable_ctrl(&old_msk); trap_flag = FALSE; } /* * If func is SIG_IGN, leave the TT channel closed and the * system response to interrupts enabled for system() calls. */ if (func == SIG_IGN) return; /* * If we get to here, we have a LYNX func, so set the AST. */ lib$disable_ctrl(&mask, &old_msk); trap_flag = TRUE; status = sys$assign (&term_nam_dsc, &iochan, 0, 0 ); status = sys$qiow ( EFN, iochan, IO$_SETMODE|IO$M_CTRLCAST|IO$M_CTRLYAST, &iosb, 0, 0, func, SIGINT, 0, 0, 0, 0 );} /* VMSsignal *//* * DCLspawn_exception, spawn_DCLprocess, DCLsystem -- F.Macrides 16-Jan-1994 * Exception-handler routines for regulating interrupts and enabling * Control-T during spawns. Includes TRUSTED flag for versions of VMS * which require it in captive accounts. This code should be used * instead of the VAXC or DECC system(), by including LYSystem.h in * modules which have system() calls. It helps ensure that we return * to Lynx instead of breaking out to DCL if a user issues interrupts * or generates an ACCVIO during spawns. */#ifdef __DECCPRIVATE unsigned int DCLspawn_exception ARGS2( void *, sigarr, void *, mecharr){#elsePRIVATE int DCLspawn_exception ARGS2( void *, sigarr, void *, mecharr){#endif /* __DECC */ int status; status = lib$sig_to_ret(sigarr, mecharr); return(SS$_UNWIND);}PRIVATE int spawn_DCLprocess ARGS1( char *, command){ int status; unsigned long Status = 0; /* * Keep DECC from complaining. */ struct dsc$descriptor_s command_desc; command_desc.dsc$w_length = strlen(command); command_desc.dsc$b_class = DSC$K_CLASS_S; command_desc.dsc$b_dtype = DSC$K_DTYPE_T; command_desc.dsc$a_pointer = command; VAXC$ESTABLISH(DCLspawn_exception);#ifdef __ALPHA /** OpenVMS/AXP lacked the TRUSTED flag before v6.1 **/ if (VersionVMS[1] > '6' || (VersionVMS[1] == '6' && VersionVMS[2] == '.' && VersionVMS[3] >= '1')) {#else if (VersionVMS[1] >= '6') {#endif /* __ALPHA */ /* * Include TRUSTED flag. */ unsigned long trusted = CLI$M_TRUSTED; status = lib$spawn(&command_desc,0,0,&trusted, 0,0,&Status); /* * If it was invalid, try again without the flag. */ if (status == LIB$_INVARG) status = lib$spawn(&command_desc,0,0,0, 0,0,&Status ); } else status = lib$spawn(&command_desc,0,0,0, 0,0,&Status); /* * Return -1 on error. */ if ((status&1) != 1 || (Status&1) != 1) return(-1); /* * Return 0 on success. */ return(0);}PUBLIC int DCLsystem ARGS1( char *, command){ int status; extern void controlc(); VMSsignal(SIGINT, SIG_IGN); status = spawn_DCLprocess(command); VMSsignal(SIGINT, cleanup_sig); /* * Returns 0 on success, -1 any error. */ return(status);}#endif /* VMS */PUBLIC void lynx_force_repaint NOARGS{#if defined(COLOR_CURSES) chtype a;#ifndef USE_COLOR_STYLE if (LYShowColor >= SHOW_COLOR_ON) a = COLOR_BKGD; else#endif a = A_NORMAL; bkgdset(a | ' ');#ifndef USE_COLOR_STYLE bkgd(a | ' ');#endif attrset(a);#endif /* COLOR_CURSES */ clearok(curscr, TRUE);}PUBLIC void lynx_start_title_color NOARGS{}PUBLIC void lynx_stop_title_color NOARGS{}PUBLIC void lynx_start_link_color ARGS2( int, flag, int, pending){ if (flag) { /* makes some terminals work wrong because * they can't handle two attributes at the * same time */ /* start_bold(); */ start_reverse();#if defined(USE_SLANG) if (SLtt_Use_Ansi_Colors) start_underline ();#endif /* USE_SLANG */#if defined(FANCY_CURSES) && defined(COLOR_CURSES) if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) start_underline ();#endif /* USE_SLANG */ } else { start_bold(); /* * Make sure when flag is OFF that "unhighlighted" links * will be underlined if appropriate. - LE & FM */ if (pending) start_underline(); }}PUBLIC void lynx_stop_link_color ARGS2( int, flag, int, pending){#ifdef USE_COLOR_STYLE LynxChangeStyle(flag == ON ? s_alink : s_a, ABS_OFF, 0);#else if (flag) { stop_reverse();#if defined(USE_SLANG) if (SLtt_Use_Ansi_Colors) stop_underline ();#endif /* USE_SLANG */#if defined(FANCY_CURSES) && defined(COLOR_CURSES) if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) stop_underline ();#endif /* FANCY_CURSES && COLOR_CURSES */ } else { stop_bold(); /* * If underlining was turned on above, turn it off. - LE & FM */ if (pending) stop_underline(); }#endif}PUBLIC void lynx_stop_target_color NOARGS{ stop_underline(); stop_reverse(); stop_bold();}PUBLIC void lynx_start_target_color NOARGS{ start_bold(); start_reverse(); start_underline();}PUBLIC void lynx_start_status_color NOARGS{#if USE_COLOR_TABLE && defined(COLOR_CURSES) if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) lynx_set_color (2); else#endif start_reverse ();}PUBLIC void lynx_stop_status_color NOARGS{#if USE_COLOR_TABLE && defined(COLOR_CURSES) if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) lynx_set_color (0); else#endif stop_reverse ();}PUBLIC void lynx_start_h1_color NOARGS{ if (bold_H1 || bold_headers) start_bold();}PUBLIC void lynx_stop_h1_color NOARGS{ if (bold_H1 || bold_headers) stop_bold();}PUBLIC void lynx_start_prompt_color NOARGS{ start_reverse ();}PUBLIC void lynx_stop_prompt_color NOARGS{ stop_reverse ();}PUBLIC void lynx_start_radio_color NOARGS{ start_bold ();}PUBLIC void lynx_stop_radio_color NOARGS{ stop_bold ();}PUBLIC void lynx_stop_all_colors NOARGS{ stop_underline (); stop_reverse (); stop_bold ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -