📄 ledlib.c
字号:
/* ledLib.c - line-editing library *//* Copyright 1984-2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------02w,18oct01,fmk add routine description to fix doc build errors02v,27sep01,dcb Fix SPR 21697. Free the ledId that was allocated in ledOpen. Compiler warning clean up.02u,14jul97,dgp doc: change ^ to CTRL- in cursor movement descriptions02t,31oct96,elp Replaced symAdd() call by symSAdd() call (symtbls synchro).02s,23nov93,jmm ledRead now ignores NULL characters (spr 2666)02r,20jan93,jdi documentation cleanup for 5.1.02q,19oct92,jcf fixed esc-space garbage.02p,23aug92,jcf fixed esc-k garbage when first commaned.02o,20jul92,jmm added group parameter to symAdd call02n,18jul92,smb Changed errno.h to errnoLib.h.02m,26may92,rrr the tree shuffle02l,19mar92,jmm fixed problem in histAdd and histAll w/long lines in history SPR #138102k,20dec91,gae stopped blow ups when using history for first time. removed nulls from output stream in histAll().02j,10dec91,gae added includes for ANSI.02i,04oct91,rrr passed through the ansification filter -changed functions to ansi style -changed includes to have absolute path from h/ -fixed #else and #endif -changed VOID to void -changed copyright notice02h,05apr91,jdi documentation -- removed header parens and x-ref numbers; doc review by gae.02g,08feb91,jaa documentation cleanup.02f,25oct90,gae fixed ignoring of previously set ty options - per Hdei Nunoe.02e,10aug90,dnw changed declaration of ledClose from void to STATUS.02d,10aug90,kdl added forward declarations for functions returning void.02c,11may90,yao added missing modification history (02b) for the last checkin.02b,09may90,yao typecasted malloc to (char *).02a,15apr90,jcf changed symbol type to SYM_TYPE.01z,14mar90,jdi documentation cleanup.01y,22feb90,dab fixed glitch in ledRead()'s 's' cmd. documentation.01x,10nov89,dab fixed 'x' cmd bug in ledRead(). fixed bfill() bug in ledRead(). fixed EOF bug in ledRead(). added 's' cmd to ledRead()'s vi interface.01w,13jun89,gae fixed glitch in 01v caused by histSize not being init'd.01v,01may89,dab histInit() now keeps past history when size is changed.01u,24sep88,gae documentation touchup.01t,30aug88,gae documentation.01s,10aug88,gae fixed "static" bug in histInit()01r,22jun88,dnw changed bmove() to bcopy() since bcopy() now handles overlapping buffers.01q,30may88,dnw changed to v4 names.01p,09nov87,gae changed name (again) from kornLib.c.01o,03nov87,ecs documenation.01n,02nov87,gae documenation.01m,24oct87,gae changed name from shellLib.c. Fixed history mechanism: added histInit() and removed built-in "h".01l,17aug87,gae Made re-entrant, viz. useable by programs other than the shell. Fixed history bug. Added symbol name completion.01k,24jul87,gae imported ty{Backspace,DeleteLine,Eof}Char's from tyLib.c and used instead of constants.01j,07apr87,jlf deleted shHistDelete, which was unused, to appease lint.01i,01apr87,ecs delinted.01h,19mar87,jlf added copyright. +gae minor fixes for mangen. documentation.01g,12mar87,gae little fix in shHistFind() for bug with 'n'.01f,02feb87,gae added writex() so control chars will be printed as '?'; also done in shHistAll(). Improved motion (maybe); added redraw (^L); made undo nicer; allowed replace to be cancelled with ESC; fixed shHistFind() bug. Added UNIX_DEBUG ability.01e,19jan87,gae included memLib.h to appease lint.01d,14jan87,gae made history use a free list, history search works within lines not just at beginning, command mode default after search, made history number increment properly; saved space by making curLn a pointer to the user's string, and more...01c,20dec86,dnw changed to not get include files from default directories. replaced spaces[] and bksps[] with writen() (vax compiler complained about line too long).01b,18dec86,gae various bug fixes & improvements.01a,23oct86,gae written*//*DESCRIPTIONThis library provides a line-editing layer on top of a `tty' device.The shell uses this interface for its history-editing features.The shell history mechanism is similar to the UNIX Korn shell historyfacility, with a built-in line-editor similar to UNIX \f3vi\fP that allowspreviously typed commands to be edited. The command h() displays the 20most recent commands typed into the shell; old commands fall off the topas new ones are entered.To edit a command, type ESC to enter edit mode, and use the commandslisted below. The ESC key switches the shell to edit mode. The RETURNkey always gives the line to the shell from either editing or input mode.The following list is a summary of the commands available in edit mode..TStab(|);l slf9 l.Movement and search commands:.sp .25<n>G | - Go to command number <n>./<s> | - Search for string <s> backward in history.?<s> | - Search for string <s> forward in history.n | - Repeat last search.N | - Repeat last search in opposite direction.<n>k | - Get <n>th previous shell command in history.<n>- | - Same as "k".<n>j | - Get <n>th next shell command in history.<n>+ | - Same as "j".<n>h | - Move left <n> characters.CTRL-H | - Same as "h".<n>l | - Move right <n> characters.\f1SPACE\fP | - Same as "l".<n>w | - Move <n> words forward.<n>W | - Move <n> blank-separated words forward.<n>e | - Move to end of the <n>th next word.<n>E | - Move to end of the <n>th next blank-separated word.<n>b | - Move back <n> words.<n>B | - Move back <n> blank-separated words.f<c> | - Find character <c>, searching forward.F<c> | - Find character <c>, searching backward.^ | - Move cursor to first non-blank character in line.$ | - Go to end of line.0 | - Go to beginning of line..T&l slf9 l.Insert commands (input is expected until an ESC is typed):.sp .25a | - Append.A | - Append at end of line.c \f1SPACE\fP | - Change character.cl | - Change character.cw | - Change word.cc | - Change entire line.c$ | - Change everything from cursor to end of line.C | - Same as "c$".S | - Same as "cc".i | - Insert.I | - Insert at beginning of line.R | - Type over characters..T&l slf9 l.Editing commands:.sp .25<n>r<c> | - Replace the following <n> characters with <c>.<n>x | - Delete <n> characters starting at cursor.<n>X | - Delete <n> characters to the left of the cursor.d \f1SPACE\fP | - Delete character.dl | - Delete character.dw | - Delete word.dd | - Delete entire line.d$ | - Delete everything from cursor to end of line.D | - Same as "d$".p | - Put last deletion after the cursor.P | - Put last deletion before the cursor.u | - Undo last command.~ | - Toggle case, lower to upper or vice versa..T&l slf9 l.Special commands:.sp .25CTRL-U | - Delete line and leave edit mode.CTRL-L | - Redraw line.CTRL-D | - Complete symbol name.\f1RETURN\fP | - Give line to shell and leave edit mode..TEThe default value for <n> is 1.DEFICIENCIESSince the shell toggles between raw mode and line mode, type-ahead can belost. The ESC, redraw, and non-printable characters are built-in. TheEOF, backspace, and line-delete are not imported well from tyLib.Instead, tyLib should supply and/or support these charactersvia ioctl().Some commands do not take counts as users might expect. For example,"<n>i" will not insert whatever was entered <n> times.INCLUDE FILES: ledLib.hSEE ALSO:.pG "Shell"INTERNALLINE_LEN should be specifed elsewhere.In an attempt to economize shell stack space, the "string" parameter iswritten in up to LINE_LEN! An EOS is used at the beginning of the stringas well, thus only LINE_LEN-1 places are returned.*/#include "vxWorks.h"#include "ctype.h"#include "errnoLib.h"#include "ioLib.h"#include "lstLib.h"#include "memLib.h"#include "stdlib.h"#include "stdio.h"#include "unistd.h"#include "string.h"#include "iosLib.h"#include "sysSymTbl.h"#include "symLib.h"#include "symbol.h"/* to debug under UNIX:cc -O -I$vh -DPORTABLE -c bLib.ccc -O -I$vh -DUNIX_DEBUG -o ledLib ledLib.c $v/lib/host/vxWorks.a symLib.o bLib.o*/#ifdef UNIX_DEBUG#undef EOF#undef NULL#include "stdio.h"char tyBackspaceChar = 0x08; /* default is control-H */char tyDeleteLineChar = 0x15; /* default is control-U */char tyEofChar = 0x04; /* default is control-D */SYMTAB_ID sysSymTbl;#endif /* UNIX_DEBUG */IMPORT char tyBackspaceChar; /* default is control-H */IMPORT char tyDeleteLineChar; /* default is control-U */IMPORT char tyEofChar; /* default is control-D */#define CMP_CHAR 0x04 /* symbol name completion */#define BEL_CHAR 0x07 /* bell */#define RET_CHAR '\n' /* return */#define ESC_CHAR 0x1b /* escape */#define NON_CHAR '?' /* non-printable char. representation */#define RDW_CHAR 0x0c /* redraw */#define LINE_LEN 128 /* >= MAX_SHELL_LINE! */#define BACKWARD (-1)#define FORWARD 1#define save() if (strlen (saveLn) == 0) strcpy (saveLn, curLn)typedef struct /* CMP_ARG */ { int count; int nameLen; char *name; char *match; } CMP_ARG;typedef struct /* HIST */ { NODE node; char line [LINE_LEN+1]; } HIST;typedef struct /* LED */ { int inFd; int outFd; int histSize; LIST histFreeList; LIST histList; HIST *pHist; /* XXX the following are not needed between ledRead's * but are used in support routines. */ char *buffer; /* hold deletions from curLn */ int histNum; /* current history number */ BOOL cmdMode; /* insert or command mode */ } LED;typedef LED *LED_ID;/* forward static functions */static void setPreempt (FUNCPTR *catchFunc, FUNCPTR func);static int preempt (FUNCPTR *catchFunc, char ch, char *curLn, int *curPs, int *number, LED_ID ledId);static void redraw (int outFd, char *oldLn, int lastPs, char *curLn, int *curPs);static BOOL completeName (char *curLn, int *curPs);static BOOL findName (char *name, char *value, SYM_TYPE type, CMP_ARG *arg);static void search (BOOL ignorePunct, BOOL endOfWord, char *curLn, int *curPs, int dir);static BOOL find (char ch, char *curLn, int *curPs, int dir);static STATUS findFwd (char ch, char *curLn, int *curPs, int *number);static STATUS findBwd (char ch, char *curLn, int *curPs, int *number);static STATUS change (char ch, char *curLn, int *curPs, int *number, LED_ID ledId);static STATUS deletec (char ch, char *curLn, int *curPs, int *number, LED_ID ledId);static STATUS replace (char ch, char *curLn, int *curPs, int *number);static void beep (int outFd);static int writex (int fd, char buffer [ ], int nbytes);static int writen (int fd, char ch, int nbytes);static void histInit (LED_ID ledId, int histSize);static void histAdd (LED_ID ledId, char *line);static BOOL histNum (LED_ID ledId, char *line, int n);static STATUS histNext (LED_ID ledId, char *line);static STATUS histPrev (LED_ID ledId, char *line);static BOOL histFind (LED_ID ledId, char *match, char *line);static void histAll (LED_ID ledId);/********************************************************************************* ledOpen - create a new line-editor ID** This routine creates the ID that is used by ledRead(), ledClose(), and* ledControl(). Storage is allocated for up to <histSize> previously read* lines.** RETURNS: The line-editor ID, or ERROR if the routine runs out of memory.** SEE ALSO: ledRead(), ledClose(), ledControl()*/int ledOpen ( int inFd, /* low-level device input fd */ int outFd, /* low-level device output fd */ int histSize /* size of history list */ ) { LED_ID ledId = (LED_ID)calloc (1, sizeof (LED)); if (ledId == NULL) return (ERROR); if ((ledId->buffer = (char *) malloc (LINE_LEN + 1)) == NULL) return (ERROR); ledId->inFd = inFd; ledId->outFd = outFd; lstInit (&ledId->histList); lstInit (&ledId->histFreeList); histInit (ledId, histSize); return ((int) ledId); }/********************************************************************************* ledClose - discard the line-editor ID** This routine frees resources allocated by ledOpen(). The low-level* input/output file descriptors are not closed.** RETURNS: OK.** SEE ALSO: ledOpen()*/STATUS ledClose ( int led_id /* ID returned by ledOpen */ ) { FAST LED_ID ledId = (LED_ID)led_id; lstFree (&ledId->histList); lstFree (&ledId->histFreeList); free (ledId->buffer); free (ledId); return (OK); }/********************************************************************************* ledRead - read a line with line-editing** This routine handles line-editing and history substitutions.* If the low-level input file descriptor is not in OPT_LINE mode,* only an ordinary read() routine will be performed.** RETURNS: The number of characters read, or EOF.*/int ledRead ( int led_id, /* ID returned by ledOpen */ char *string, /* where to return line */ int maxBytes /* maximum number of chars to read */ ) { FAST LED_ID ledId = (LED_ID)led_id; FAST int ix; /* the ubiquitous */ char ch; /* last character entered */ BOOL overStrike = FALSE; /* in over-strike mode */ BOOL srchMode = FALSE; /* entering search characters */ BOOL done = FALSE; /* return has been entered */ int returnVal = EOF; /* number of characters or EOF */ int result; /* return value from preempt */ char oldLn [LINE_LEN+1]; /* current line before most recent input*/ char saveLn [LINE_LEN+1]; /* saved version of line before changes */ char histLn [LINE_LEN+1]; /* last version of historical line */ char *curLn; /* current line, points to user's string*/ int curPs = 0; /* current cursor position */ int lastPs = 0; /* last position cursor was at */ int number = 0; /* repeat factor */ FUNCPTR catchFunc; /* preempt routine */#ifndef UNIX_DEBUG int oldoptions = ioctl (ledId->inFd, FIOGETOPTIONS, 0 /*XXX*/); /* XXX should be check for ERROR except an option might be 0xff, * perhaps inspect errno for valid 'fd', or something. */ /* if not in line mode, just do plain read */ if (!(oldoptions & OPT_LINE)) return (read (ledId->inFd, string, maxBytes)); /* turn off echo & line mode */ ioctl (ledId->inFd, FIOSETOPTIONS, oldoptions & ~(OPT_LINE | OPT_ECHO));#endif /* UNIX_DEBUG */ bzero (string, maxBytes); string [0] = EOS; /* Beginning Of String */ curLn = &string [1]; /* reserve position 0 for EOS (BOS) */ saveLn [0] = EOS; histLn [0] = EOS; setPreempt (&catchFunc, (FUNCPTR) NULL); ledId->buffer [0] = EOS; ledId->cmdMode = FALSE; bfill (oldLn, LINE_LEN+1, EOS); bfill (curLn, maxBytes - 1, EOS); /* -1 cause of BOS */ /* operation: * redraw line, * read next character, * based on command/input mode perform appropriate action, * loop. */ while (! done) { redraw (ledId->outFd, oldLn, lastPs, curLn, &curPs); lastPs = curPs; strcpy (oldLn, curLn); if (read (ledId->inFd, &ch, 1) < 1) { done = TRUE; returnVal = EOF; break; } /* Ignore NULL in the input stream */ if (ch == (char)NULL) continue; /* some function wants to preempt? */ result = preempt (&catchFunc, ch, curLn, &curPs, &number, ledId); if (result == ERROR) { beep (ledId->outFd); continue; /* short-cut loop */ } else if (result == OK) continue; /* short-cut loop */ if (ledId->cmdMode) { /* parse command */ if (ch == tyBackspaceChar) ch = 'h'; if (ch == tyDeleteLineChar) { ledId->cmdMode = FALSE; curLn [0] = EOS; curPs = 0; } else switch (ch) { case 'G': save(); if (number < 1) number = 1; if (histNum (ledId, curLn, number)) curPs = 0; else beep (ledId->outFd); number = 0; break; case '/': case '?': strcpy (saveLn, curLn); srchMode = TRUE; ledId->cmdMode = FALSE; curLn [0] = ch; curLn [1] = EOS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -