📄 ecurcvr.c
字号:
/* #define DEFENSIVE *//* #define ANSI_DEBUG */ /* debug ansi *//* #define ANSI_DEBUG_2 */ /* debug ansi intensive output *//* #define ANSI_DEBUG_3 */ /* debug ansi selected output *//* #define ANSI_DEBUG_NOBUF */ /* unbufferred logging *//* #define ANSI_DEBUG_LOGFILE "/dev/tty2h" *//* #define DEBUG_CURSOR */#ifndef LIMIT_BELL#define LIMIT_BELL#endif/*+------------------------------------------------------------------------- ecurcvr.c - rcvr process + ANSI filter + non-ANSI<->ANSI hoop jumping wht@n4hgf.Mt-Park.GA.US Defined functions: accumulate_ansi_sequence(rchar) ansi_CNL() ansi_CPL() ansi_CUB() ansi_CUD() ansi_CUF() ansi_CUP() ansi_CUU() ansi_DCH() ansi_DL() ansi_DSR() ansi_ECH() ansi_ED() ansi_EL() ansi_HPA() ansi_ICH() ansi_IL() ansi_SD() ansi_SGR() ansi_SU() ansi_VPA() is_ansi_terminator(rchar) lgetc_rcvr() process_ansi_sequence() process_rcvd_char(rchar) rcvd_ESC() rcvr() rcvr_log_open() rcvrdisp(buf,buflen) rcvrdisp_actual() rcvrdisp_actual2() redisplay_rcvr_screen() saved_cursor_restore_cursor() saved_cursor_save_cursor() spaces(buf,buflen) spaces_trap(code,buf,buflen)--------------------------------------------------------------------------*//*+:EDITS:*//*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 *//*:09-06-1992-13:29-wht@n4hgf-add receiver process buffered screen write *//*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA *//*:05-29-1992-13:28-wht@n4hgf-no banner - phone numbers are security risk *//*:11-11-1991-14:25-wht@n4hgf-lzero_length_read_detected code *//*:11-11-1991-12:45-wht@n4hgf-add LIMIT_BELL code *//*:08-26-1991-16:39-wht@n4hgf2-SD was still hopelessly manic *//*:07-25-1991-12:56-wht@n4hgf-ECU release 3.10 *//*:07-05-1991-06:13-wht@n4hgf-SD was in baaaaadd shape *//*:01-09-1991-22:31-wht@n4hgf-ISC port *//*:12-26-1990-14:32-wht@n4hgf-use memset in spaces() *//*:12-21-1990-21:06-wht@n4hgf-CUF and CUB set non-ansi cursor incorrectly *//*:12-20-1990-16:27-wht@n4hgf-had SU and SD swapped *//*:11-30-1990-18:39-wht@n4hgf-non-ansi console rcvr appears to be working *//*:11-28-1990-14:13-wht@n4hgf-start non-ansi console support *//*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */#include "ecu.h"#include "ecukey.h"#include <sys/ipc.h>#include <sys/sem.h>extern int errno;extern char rcvr_log_file[]; /* if rcvr_log!= 0,log filename */extern int rcvr_log; /* rcvr log active if != 0 */extern FILE *rcvr_log_fp; /* rcvr log file */extern int rcvr_log_raw; /* if true, log all, else filter ctl chrs */extern int rcvr_log_append; /* if true, append, else scratch */extern int rcvr_log_flusheach; /* if true, flush log on each char */extern int rcvr_log_gen_title;extern uint tcap_LINES; /* terminal line quantity - see ecutcap.c */extern uint tcap_COLS; /* terminal column quantity - see ecutcap.c */extern uint LINESxCOLS;static char esc = ESC;#define MAX_ANSI_LEN 30 /* generous */char ansibuf[MAX_ANSI_LEN];char *ansi;int ansilen = 0;int in_ansi_accumulation = 0;int saved_cursor_y;int saved_cursor_x;#define RCVR_RDQUAN 250char lgetc_buf[RCVR_RDQUAN];char *lgetc_ptr;extern int lgetc_count;uchar autorz_frame[] = { SUB, 'B', '0', '0' };#ifdef ANSI_DEBUGFILE *wfp = (FILE *)0;#endifuchar non_multiscreen_hi_map[128] = {/*80*/ 'c','u','e','a','a','a','a','c', /* the main purpose of this ... *//*88*/ 'e','e','e','i','i','i','a','a', /* ... is to map ruling ... *//*90*/ 'e','e','a','a','a','o','u','u', /* ... characters, but as ...*//*98*/ 'y','o','u','X','#','Y','P','f', /* ... a side effect, also map ... *//*A0*/ 'a','i','o','u','n','n','a','o', /* ... others to reasonable, ... *//*A8*/ '?','-','-','%','%','|','<','>', /* ... near, amusing, or random ... *//*B0*/ '#','#','#','|','+','+','+','.', /* ... printing characters as well *//*B8*/ '.','+','|','.','\'','\'','\'','.',/*C0*/ '`','+','+','+','-','+','+','+',/*C8*/ '`','.','+','+','+','=','+','+',/*D0*/ '+','+','+','`','`','.','.','+',/*D8*/ '+','\'','.','#','_','|','|','-',/*E0*/ 'a','b','F','T','E','o','u','t',/*E8*/ 'I','0','O','o','o','o','e','n',/*F0*/ '=','+','>','<','f','j','%','=',/*F8*/ 'o','.','.','V','n','2','*',' '};/* * if != 0, allow xmtr use of rcvrdisp_actual2() function to buffer, * if 0, flush buffer whenever the function is called */int rcvrdisp_actual2_xmtr_buffer = 0;/*+------------------------------------------------------------------------- rcvrdisp_p() - lock rcvrdisp mechanism--------------------------------------------------------------------------*/#ifdef RCVRDISP_PVvoidrcvrdisp_p(){ register int retn; struct sembuf sembuf; sembuf.sem_num = 0; sembuf.sem_op = -1; sembuf.sem_flg = 0; while(1) { if(((retn = semop(shm->rcvrdisp_semid,&sembuf,1)) >= 0) || (errno != EINTR)) { break; } } if((retn < 0) && (errno != EINVAL)) { extern char lopen_err_str[]; strcpy(lopen_err_str,"rcvrdisp_p failed: SysV IPC error"); termecu(TERMECU_IPC_ERROR); }} /* end of rcvrdisp_p */#endif /* RCVRDISP_PV *//*+------------------------------------------------------------------------- rcvrdisp_v() - unlock rcvrdisp mechanism--------------------------------------------------------------------------*/#ifdef RCVRDISP_PVvoidrcvrdisp_v(){ register int retn; struct sembuf sembuf; sembuf.sem_num = 0; sembuf.sem_op = 1; sembuf.sem_flg = 0; while(1) { if(((retn = semop(shm->rcvrdisp_semid,&sembuf,1)) >= 0) || (errno != EINTR)) { break; } } if((retn < 0) && (errno != EINVAL)) { extern char lopen_err_str[]; strcpy(lopen_err_str,"rcvrdisp_v failed: SysV IPC error"); termecu(TERMECU_IPC_ERROR); }} /* end of rcvrdisp_v */#endif /* RCVRDISP_PV *//*+------------------------------------------------------------------------- rcvrdisp_actual() - actual write to screen--------------------------------------------------------------------------*/voidrcvrdisp_actual(){#ifdef RCVRDISP_PV rcvrdisp_p();#endif /* RCVRDISP_PV */ if(shm->rcvrdisp_count) write(TTYOUT,shm->rcvrdisp_buffer,shm->rcvrdisp_count); shm->rcvrdisp_ptr = shm->rcvrdisp_buffer; shm->rcvrdisp_count = 0;#ifdef RCVRDISP_PV rcvrdisp_v();#endif /* RCVRDISP_PV */} /* end of rcvrdisp_actual *//*+------------------------------------------------------------------------- rcvrdisp_actual2() - for tcap, flush only if not receiver--------------------------------------------------------------------------*/voidrcvrdisp_actual2(){ if(rcvrdisp_actual2_xmtr_buffer || (getpid() == rcvr_pid)) return;#ifdef RCVRDISP_PV rcvrdisp_p();#endif /* RCVRDISP_PV */ if(shm->rcvrdisp_count) write(TTYOUT,shm->rcvrdisp_buffer,shm->rcvrdisp_count); shm->rcvrdisp_ptr = shm->rcvrdisp_buffer; shm->rcvrdisp_count = 0;#ifdef RCVRDISP_PV rcvrdisp_v();#endif /* RCVRDISP_PV */} /* end of rcvrdisp_actual2 *//*+------------------------------------------------------------------------- rcvrdisp(buf,buflen) - logical write to screen--------------------------------------------------------------------------*/voidrcvrdisp(buf,buflen)char *buf;int buflen;{ if((buflen + shm->rcvrdisp_count) > sizeof(shm->rcvrdisp_buffer)) rcvrdisp_actual(); if((buflen + shm->rcvrdisp_count) > sizeof(shm->rcvrdisp_buffer)) { write(TTYOUT,buf,buflen); return; }#ifdef RCVRDISP_PV rcvrdisp_p();#endif /* RCVRDISP_PV */ memcpy(shm->rcvrdisp_ptr,buf,buflen); shm->rcvrdisp_ptr += buflen; shm->rcvrdisp_count += buflen;#ifdef RCVRDISP_PV rcvrdisp_v();#endif /* RCVRDISP_PV */} /* end of rcvrdisp *//*+------------------------------------------------------------------------- redisplay_rcvr_screen() - redisplay logical receiver screenAs of writing, this function is called only by the XMTR process--------------------------------------------------------------------------*/voidredisplay_rcvr_screen(){ register uint y; extern int tty_not_char_special; if(tty_not_char_special) return; setcolor(colors_current); tcap_stand_end(); for(y = 0; y < tcap_LINES; y++) { tcap_cursor(y,0); fwrite(&shm->screen[y][0], ((y != tcap_LINES - 1) ? tcap_COLS : tcap_COLS - 1),1,se); } tcap_eeol(); tcap_cursor(shm->cursor_y,shm->cursor_x);} /* end of redisplay_rcvr_screen */#ifdef DEBUG_CURSORvoidspaces_trap(code,buf,buflen)int code;register uchar *buf;register uint buflen;{ char *xyz = (char *)0x90000000; ff(se,"rcvr 'spaces trap' code %d: cursor x,y=%d,%d\r\n", code, shm->cursor_y,shm->cursor_x); ff(se,"buf=%08lx len=%08lx offs=%08lx\r\n",buf,buflen, (ulong)buf - (ulong)shm->screen); *xyz = 0; abort();}#endif/*+------------------------------------------------------------------------- spaces(buf,buflen) - fill with spaces--------------------------------------------------------------------------*/voidspaces(buf,buflen)register uchar *buf;uint buflen;{#ifdef DEBUG_CURSOR if((ulong)buf > (((ulong)shm->screen) + LINESxCOLS)) spaces_trap(1,buf,buflen); if((ulong)buf < (ulong)shm->screen) spaces_trap(2,buf,buflen); if((ulong)(buf + buflen) > (((ulong)shm->screen) + LINESxCOLS)) spaces_trap(3,buf,buflen); if((ulong)(buf + buflen) < (ulong)shm->screen) spaces_trap(4,buf,buflen);#endif if(!buflen) return;#ifdef DEFENSIVE if((ulong)buf < (ulong)shm->screen) return; if((ulong)(buf + buflen) > (((ulong)shm->screen) + LINESxCOLS)) return;#endif memset(buf,SPACE,buflen);} /* end of spaces *//*+------------------------------------------------------------------------- lgetc_rcvr() - rcvr version of get char from line--------------------------------------------------------------------------*/intlgetc_rcvr(){ extern int errno; if(!lgetc_count) { rcvrdisp_actual(); while(lgetc_count <= 0) { errno = 0; if((lgetc_count = read(shm->Liofd,lgetc_buf,RCVR_RDQUAN)) < 0) { if(errno == EINTR) /* if signal interrupted, ... */ continue; /* ... read again */ termecu(TERMECU_LINE_READ_ERROR); } if(!lgetc_count) { lzero_length_read_detected(); /* maybe terminate program ... */ continue; /* ... but if not, read again */ } } shm->rcvd_chars += lgetc_count; shm->rcvd_chars_this_connect += lgetc_count; lgetc_ptr = lgetc_buf; } lgetc_count--; if(shm->Lparity) return(*lgetc_ptr++ & 0x7F); else return(*lgetc_ptr++);} /* end of lgetc_rcvr *//*+------------------------------------------------------------------------- ansi_SGR() - Set Graphics RenditionThe DOS ANSI world expects to be able to be able to chain 0,1 and3x,4x params together with semicolons. Supported modifiers for non-ansi terminals 0 normal 1 bold 4 underscore 5 blink 7 reverse video--------------------------------------------------------------------------*/voidansi_SGR(){ register itmp; register char *cptr; char SGRstr[MAX_ANSI_LEN]; char *token; char *str_token(); if(!tty_is_multiscreen) { ansibuf[ansilen - 1] = 0; /* get rid of 'm' */ cptr = ansibuf + 1; /* get rid of '[' */ if(!strlen(cptr)) goto SGR_0; while(token = str_token(cptr,";")) { cptr = (char *)0; /* further calls to str_token need NULL */ switch(atoi(token)) { default: case 0: /* normal */SGR_0: tcap_stand_end(); tcap_blink_off(); tcap_underscore_off(); tcap_bold_off(); break; case 1: /* bold */ tcap_bold_on(); break; case 4: /* underscore */ tcap_underscore_on(); break; case 5: /* blink */ tcap_blink_on(); break; case 7: /* reverse video */ tcap_stand_out(); break; } } return; } if(ansilen <= 3) /* 'ESC[<0-9>m' and 'ESC[m' - quickly handled */ { rcvrdisp(&esc,1); rcvrdisp(ansibuf,ansilen); return; }/* check XENIX 'ESC[<2,3,7>m' extensions */ switch(itmp = atoi(ansibuf + 1)) { case 7: /* XENIX 'ESC[7;<0-15>;<0-15>m' set fore/background color */ itmp = atoi(ansibuf + 3); /* second parameter */ if(itmp > 15) /* not XENIX extension */ break; /* fall through */ case 2: /* XENIX 'ESC[2;<0-15>;<0-15>m' set fore/background color */ case 3: /* XENIX 'ESC[3;<0-1>m' color only set/clear blink */ rcvrdisp(&esc,1); rcvrdisp(ansibuf,ansilen); return; default: break; }/* not XENIX extension */ ansibuf[ansilen - 1] = 0; /* get rid of 'm' */ cptr = ansibuf + 1; /* get rid of '[' */ while(token = str_token(cptr,";")) { cptr = (char *)0; /* further calls to str_token need NULL */ sprintf(SGRstr,"\033[%sm",token); rcvrdisp(SGRstr,strlen(SGRstr)); }} /* end of ansi_SGR *//*+------------------------------------------------------------------------- ansi_CUP() - cursor position (also HVP horiz/vertical position)--------------------------------------------------------------------------*/voidansi_CUP(){ register uint param_count = 0; char ansicopy[MAX_ANSI_LEN]; register char *cptr = ansicopy; register char *token; char *str_token(); strcpy(cptr,ansibuf + 1); *(cptr + ansilen - 2) = 0; while(token = str_token(cptr,";")) { cptr = (char *)0; /* further calls to str_token need NULL */ switch(++param_count) { case 1: shm->cursor_y = atoi(token) - 1; break; case 2: shm->cursor_x = atoi(token) - 1; break; } } switch(param_count) { case 0: shm->cursor_y = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -