diff --git a/Makefile b/Makefile index 14ee038..d233a93 100644 --- a/Makefile +++ b/Makefile @@ -13,11 +13,6 @@ else endif export E Q -uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') -# for windows based target, insure we strip the variant part -# CYGWIN_NT-6.1, CYGWIN_NT-6.1-WOW, CYGWIN_NT-6.1-WOW64, MSYS_NT-10.0-19042 -uname_S := $(shell sh -c 'echo $(uname_S) | sed s/_.*$$//') - PROGRAM=ue CC=gcc @@ -25,18 +20,7 @@ WARNINGS=-pedantic -Wall -Wextra -Wstrict-prototypes -Wno-unused-parameter CFLAGS=-O2 $(WARNINGS) LDFLAGS=-s LIBS=-lcurses -DEFINES=-DAUTOCONF -DPROGRAM=$(PROGRAM) # -DNDEBUG -ifeq ($(uname_S),Linux) - DEFINES += -DPOSIX -DUSG -else ifeq ($(uname_S),CYGWIN) - DEFINES += -DCYGWIN -DSYSV -else ifeq ($(uname_S),MSYS) - DEFINES += -DCYGWIN -DSYSV -else ifeq ($(uname_S),NetBSD) - DEFINES += -DPOSIX -DBSD=1 -else - $(error $(uname_S) needs configuration) -endif +DEFINES=-DPROGRAM=$(PROGRAM) -D_GNU_SOURCE # -DNDEBUG BINDIR=/usr/bin LIBDIR=/usr/lib diff --git a/README.md b/README.md index 6ba80bf..d9aa711 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # README # -µEMACS (ue) on Cygwin/Linux, based on uEmacs/PK (em) from [kernel.org]( +µEMACS (ue) on Cygwin/Linux/NetBSD, based on uEmacs/PK (em) from [kernel.org]( https://git.kernel.org/pub/scm/editors/uemacs/uemacs.git/). ### Changes compare to uEmacs/PK ### @@ -18,14 +18,14 @@ https://git.kernel.org/pub/scm/editors/uemacs/uemacs.git/). * Some defaults changed due to 'finger habits': ue instead of em, ^S in commands mapping... +### Unicode (UTF-8) support ### + +* gcc limitation on Windows (__WCHAR_WIDTH__ 16). + +* Display of double and zero width characters ongoing. + ### How to build ### * dependencies: gcc, gmake, ncurses-devel. * make - -### Badges ### - -[![Coverity Status]( - https://scan.coverity.com/projects/4449/badge.svg)]( - https://scan.coverity.com/projects/4449) diff --git a/blindmaz.cmd b/blindmaz.cmd index ecc67cc..b0b907f 100644 --- a/blindmaz.cmd +++ b/blindmaz.cmd @@ -1,13 +1,17 @@ ## blindmaz.cmd -- solve maze by walking a left-handed blind mouse #7 set $seed -#execute-file maze.cmd +# either maze.cmd, sharpmaz.cmd or floodmaz.cmd execute-file floodmaz.cmd -set %x 2 + +set %dotc &asc "•" # alternatively use "." +set $curchar %dotc +set %x &add $curcol 1 set %y $curline end-of-line set %stopcol &sub $curcol 1 +# X-Y offset for absolute direction: east, south, west, north set %DX0 1 set %DY0 0 set %DX1 0 @@ -17,54 +21,40 @@ set %DY2 0 set %DX3 0 set %DY3 -1 -set %dotc &asc "." - -store-procedure probe - set %OX &ind &cat "%DX" %nD - set %OY &ind &cat "%DY" %nD - set %nx &add %x %OX - set %ny &add %y %OY - set $curline %ny - set $curcol %nx - !if &or &equ $curchar 32 &equ $curchar %dotc - !if &equ $curchar 32 - set %C %dotc - !else - set %C &asc " " # erase when backtracking (or highlight) - !endif - set %D %nD - set $curchar %C - set $curline %y - set $curcol %x - set $curchar %C - set %x &add %nx %OX - set %y &add %ny %OY - set $curline %y - set $curcol %x - set %res TRUE - !else - set %res FALSE - !endif - update-screen -!endm - -set %D 0 # looking EAST +set %absD 0 # absolute direction: looking EAST !while &les %x %stopcol - set %nD &mod &add %D 3 4 # Can go left? - run probe - !if &seq %res FALSE - set %nD %D # Can go straight? - run probe - !if &seq %res FALSE - set %nD &mod &add %D 1 4 # Can go right? - run probe - !if &seq %res FALSE - set %D &mod &add %D 2 4 # Go back! +# try move on left, right or front + set %relD 3 # 3, 0, 1, 2 == left, front, right, back + !while ¬ &equ %relD 2 + set %newD &mod &add %absD %relD 4 + set %offX &ind &cat "%DX" %newD + set %offY &ind &cat "%DY" %newD + set %nx &add %x %offX + set %ny &add %y %offY + set $curline %ny + set $curcol %nx + !if &or &equ $curchar 32 &equ $curchar %dotc + !if &equ $curchar 32 + set %C %dotc + !else + set %C &asc " " # erase (or highlight) when backtracking !endif + set %absD %newD + set $curchar %C + set $curline %y + set $curcol %x + set $curchar %C + set %x &add %nx %offX + set %y &add %ny %offY + update-screen + !goto moveon !endif - !endif + set %relD &mod &add %relD 1 4 + !endwhile +# else turn around + set %absD &mod &add %absD 2 4 # face back! +:moveon !endwhile -beginning-of-file -set $curline 3 -set $curcol 1 + +set $curcol &add %x -1 unmark-buffer diff --git a/buffer.c b/buffer.c index 120fc7b..8810ce8 100644 --- a/buffer.c +++ b/buffer.c @@ -1,8 +1,9 @@ /* buffer.c -- implements buffer.h */ #include "buffer.h" -/* Buffer management. Some of the functions are internal, and some are actually attached to - user keys. Like everyone else, they set hints for the display system. +/* Buffer management. Some of the functions are internal, and some are + actually attached to user keys. Like everyone else, they set hints for + the display system. modified by Petri Kutvonen */ @@ -11,9 +12,9 @@ #include #include "defines.h" -#include "estruct.h" #include "file.h" #include "input.h" +#include "list.h" #include "mlout.h" #include "utf8.h" #include "util.h" @@ -326,13 +327,12 @@ static unsigned int utf8_disp_len( const char *s) { static int makelist( int iflag) { - buffer_p bp; - int s; char line[ FNAMSTART + sizeof( fname_t)] ; blistp->b_flag &= ~BFCHG; /* Don't complain! Mute bclear() */ - if ((s = bclear(blistp)) != TRUE) /* Blow old text away */ - return s; + int s = bclear( blistp) ; /* Blow old text away */ + if( s != TRUE) + return s ; blistp->b_fname[ 0] = 0 ; /* in case of user override */ @@ -346,19 +346,15 @@ static int makelist( int iflag) { return FALSE ; /* output the list of buffers */ - for( bp = bheadp ; bp != NULL ; bp = bp->b_bufp) { /* For all buffers */ - char *cp1, *cp2 ; + for( buffer_p bp = bheadp ; bp != NULL ; bp = bp->b_bufp) { int c ; - line_p lp ; - long nbytes ; /* # of bytes in current buffer */ - long nlines ; /* # of lines in current buffer */ /* skip invisible buffers if iflag is false */ if (((bp->b_flag & BFINVS) != 0) && (iflag != TRUE)) continue; do_layout( line, bp->b_mode) ; - cp1 = line ; /* Start at left edge */ + char *cp1 = line ; /* Start at left edge */ /* output status of ACTIVE flag ('@' when the file has been read in) */ *cp1++ = (bp->b_active == TRUE) ? '@' : ' ' ; @@ -370,9 +366,10 @@ static int makelist( int iflag) { *cp1 = ((bp->b_flag & BFCHG) != 0) ? '*' : ' ' ; /* Buffer size */ - nbytes = 0L; /* Count bytes in buf. */ - nlines = 0 ; - for( lp = lforw( bp->b_linep) ; lp != bp->b_linep ; lp = lforw( lp)) { + long nbytes = 0L; /* Count bytes in buf. */ + long nlines = 0 ; + for( line_p lp = lforw( bp->b_linep) ; lp != bp->b_linep ; + lp = lforw( lp)) { nbytes += (long) llength(lp) + 1L; nlines += 1 ; } @@ -385,8 +382,8 @@ static int makelist( int iflag) { *cp1++ = ' ' ; /* Display buffer name */ - cp2 = &bp->b_bname[ 0] ; - while ((c = *cp2++) != 0) + char *cp2 = &bp->b_bname[ 0] ; + while( (c = *cp2++) != 0) *cp1++ = c; /* Pad with spaces to max buffer name length */ @@ -528,7 +525,6 @@ buffer_p bfind( const char *bname, boolean create_f, int flags) { updates that are required. Return TRUE if everything looks good. */ int bclear( buffer_p bp) { - line_p lp ; int s ; if( (bp->b_flag & (BFINVS | BFCHG)) == BFCHG /* regular and changed */ @@ -536,13 +532,28 @@ int bclear( buffer_p bp) { return s ; bp->b_flag &= ~BFCHG ; /* Not changed */ - while( (lp = lforw( bp->b_linep)) != bp->b_linep) - lfree( lp) ; + line_p lp = bp->b_linep ; + if( lp->l_fp != lp) { /* non empty buffer */ + /* turn line ring into a list and delete it */ + lp->l_bp->l_fp = NULL ; + freelist( (list_p) lp->l_fp) ; + lp->l_fp = lp->l_bp = lp ; + + /* Fix dots and marks */ + bp->b_dotp = bp->b_linep ; /* Fix "." */ + bp->b_doto = 0 ; + bp->b_markp = NULL ; /* Invalidate "mark" */ + bp->b_marko = 0 ; + if( bp->b_nwnd) /* buffer is displayed */ + for( window_p wp = wheadp ; wp ; wp = wp->w_wndp) + if( wp->w_bufp == bp) { + wp->w_linep = wp->w_dotp = lp ; + wp->w_doto = 0 ; + wp->w_markp = NULL ; + wp->w_marko = 0 ; + } + } - bp->b_dotp = bp->b_linep ; /* Fix "." */ - bp->b_doto = 0 ; - bp->b_markp = NULL ; /* Invalidate "mark" */ - bp->b_marko = 0 ; return TRUE ; } diff --git a/defines.h b/defines.h index c5959f2..1b328a4 100644 --- a/defines.h +++ b/defines.h @@ -1,17 +1,63 @@ -/* defines.h -- */ +/* defines.h -- customization based on gcc predefined macroes */ #ifndef __DEFINES_H__ #define __DEFINES_H__ -/* Must define one of - USG | BSD -*/ -#define USG 1 - -#define PKCODE 1 -#define SCROLLCODE 1 /* scrolling code P.K. */ -#define ENVFUNC 1 +#if __unix__ +# define UNIX 1 +# if __NetBSD__ +# define BSD 1 +# define POSIX 1 +# elif __linux__ +# define USG 1 +# define SVR4 1 /* locks */ +# define POSIX 1 +# else /* __CYGWIN__ */ +# define USG 1 +//# define POSIX 1 +# endif +#else +# error Missing gcc predefined __unix__ +#endif #define NSTRING 128 /* # of bytes, string buffers */ +#define TERMCAP 1 /* UNIX */ +#define XONXOFF 1 /* UNIX */ + +#define VISMAC 0 /* update display during keyboard macros */ + +#define MSDOS 0 +#define IBMPC MSDOS +#define COLOR MSDOS + + +#define FILOCK (SVR4 | BSD) +#define ENVFUNC 1 /* only two types so far (USG | BSD) */ + +#define PKCODE 1 /* include P.K. extensions, define always */ +#define SCROLLCODE 1 /* scrolling code P.K. */ + +/* Dynamic RAM tracking and reporting redefinitions */ +#define RAMSIZE 0 /* dynamic RAM memory usage tracking */ +#if RAMSIZE +# define RAMSHOW 1 /* auto dynamic RAM reporting */ +# include /* size_t */ + void *allocate( size_t size) ; + void release( void *ptr) ; + +# define malloc( sz) allocate(sz) +# define free( ptr) release( ptr) #endif -/* end of defines.h */ + +/* De-allocate memory always on exit (if the operating system or main + program can not) +*/ +#define CLEAN 0 /* de-alloc memory on exit */ +#if CLEAN +# define exit(a) cexit(a) + + void cexit( int status) ; +#endif + +#endif +/* end of predefs.h */ diff --git a/display.c b/display.c index fcf0126..4422f45 100644 --- a/display.c +++ b/display.c @@ -1,8 +1,6 @@ /* display.c -- implements display.h */ #include "display.h" -#define REVSTA 1 /* Status line appears in reverse video */ - /* The functions in this file handle redisplay. There are two halves, the ones that update the virtual display screen, and the ones that make the physical display screen the same as the virtual display screen. These @@ -11,19 +9,22 @@ Modified by Petri Kutvonen */ +#include #include +#include #include +#include +#include #include #include #include "buffer.h" -#include "estruct.h" +#include "defines.h" #include "input.h" #include "line.h" #include "termio.h" #include "terminal.h" #include "version.h" -#include "wrapper.h" #include "utf8.h" #include "window.h" @@ -45,33 +46,31 @@ typedef struct { #define VFCOL 0x0010 /* color change requested */ static video_p *vscreen ; /* Virtual screen. */ -#if MEMMAP == 0 || SCROLLCODE static video_p *pscreen ; /* Physical screen. */ -#endif - -static int displaying = TRUE ; -#if UNIX -# include -#endif #ifdef SIGWINCH # include /* for window size changes */ - int chg_width, chg_height ; + int chg_width, chg_height ; + static int displaying = TRUE ; + + static void sizesignal( int signr) ; #endif + static int currow ; /* Cursor row */ static int curcol ; /* Cursor column */ static int vtrow = 0 ; /* Row location of SW cursor */ static int vtcol = 0 ; /* Column location of SW cursor */ static int lbound = 0 ; /* leftmost column of current line being displayed */ -static int taboff = 0 ; /* tab offset for display */ int mpresf = FALSE ; /* TRUE if message in last line */ int scrollcount = 1 ; /* number of lines to scroll */ -int discmd = TRUE ; /* display command flag */ -int disinp = TRUE ; /* display input characters (echo) */ +int discmd = TRUE ; /* display command flag */ +int disinp = TRUE ; /* display input characters (echo) */ +/* global variables */ +boolean viewtab = FALSE ; /* $viewtab = TRUE to visualize hardcoded tab */ static int reframe( window_p wp) ; static void updone( window_p wp) ; @@ -84,65 +83,95 @@ static void upddex( void) ; static void updext( void) ; static void updgar( void) ; static void updpos( void) ; -static int updateline( int row, video_p vp1, video_p vp2) ; -static boolean updupd( boolean force_f) ; +static void updateline( int row) ; +static void updupd( boolean force_f) ; static void modeline( window_p wp) ; static void mlputi( int i, int r) ; static void mlputli( long l, int r) ; static void mlputf( int s) ; static void mlputs( const char *s) ; #if SIGWINCH -static int newscreensize( int h, int w) ; +static void newscreensize( int h, int w) ; #endif +/* xmalloc is used at early initialization before memory usage tracking is + enabled so it bypass the memory tracking macroes. +*/ +static void *xmalloc( size_t size) { + void *ret = (malloc)( size) ; + if( !ret) { + fprintf( stderr, "fatal: Out of memory\n") ; + exit( EXIT_FAILURE) ; + } + + return ret ; +} + /* Initialize the data structures used by the display code. The edge vectors used to access the screens are set up. The operating system's terminal I/O channel is set up. All the other things get initialized at compile time. The original window has "WFCHG" set, so that it will get completely redrawn on the first call to "update". */ -void vtinit( void) { - TTopen() ; /* open the screen */ - TTkopen() ; /* open the keyboard */ - TTrev( FALSE) ; - vscreen = xmalloc( term.t_maxrow * sizeof( video_p )) ; -#if MEMMAP == 0 || SCROLLCODE - pscreen = xmalloc( term.t_maxrow * sizeof( video_p )) ; -#endif - for( int i = 0 ; i < term.t_maxrow ; ++i) { - video_p vp = xmalloc( sizeof *vp + term.t_maxcol * sizeof( unicode_t)) ; +static int lastmrow ; /* remember mrow for later free */ + +static void vtalloc( int maxrow, int maxcol) { + lastmrow = maxrow ; /* remember mrow for later free */ + vscreen = xmalloc( maxrow * sizeof( video_p )) ; + pscreen = xmalloc( maxrow * sizeof( video_p )) ; + for( int i = 0 ; i < maxrow ; ++i) { + video_p vp = xmalloc( sizeof *vp + maxcol * sizeof( unicode_t)) ; vp->v_flag = 0 ; #if COLOR vp->v_rfcolor = 7 ; vp->v_rbcolor = 0 ; #endif vscreen[ i] = vp ; -#if MEMMAP == 0 || SCROLLCODE - vp = xmalloc( sizeof *vp + term.t_maxcol * sizeof( unicode_t)) ; + vp = xmalloc( sizeof *vp + maxcol * sizeof( unicode_t)) ; vp->v_flag = 0 ; pscreen[ i] = vp ; -#endif } } -#if CLEAN -/* free up all the dynamically allocated video structures */ +void updmargin( void) { +#define MINMARGIN 3 /* MINMARGIN - 1 enough for $ + prev before current */ +#if MINCOLS < 2 * MINMARGIN + 1 +# error "MINCOLS and MINMARGIN are not consistent" +#endif + term.t_margin = term.t_ncol / 10 ; + if( term.t_margin < MINMARGIN) + term.t_margin = MINMARGIN ; + + term.t_scrsiz = term.t_ncol - 2 * term.t_margin ; +} + +void vtinit( void) { +#ifdef SIGWINCH + signal( SIGWINCH, sizesignal) ; +#endif + + setlocale( LC_CTYPE, "") ; /* expects $LANG like en_GB.UTF-8 */ + TTopen() ; /* open the screen */ + updmargin() ; + TTkopen() ; /* open the keyboard */ + TTrev( FALSE) ; + vtalloc( term.t_mrow, term.t_mcol) ; +} + + +/* free up all the dynamically video structures allocated by vtalloc */ void vtfree( void) { - for( int i = 0 ; i < term.t_maxrow ; ++i ) { - free( vscreen[ i]) ; -#if MEMMAP == 0 || SCROLLCODE - free( pscreen[ i]) ; -#endif +/* as xmalloc bypass the malloc macro, we need bypass the free macro too */ + for( int i = 0 ; i < lastmrow ; ++i ) { + (free)( vscreen[ i]) ; + (free)( pscreen[ i]) ; } - free( vscreen) ; -#if MEMMAP == 0 || SCROLLCODE - free( pscreen) ; -#endif + (free)( vscreen) ; + (free)( pscreen) ; } -#endif /* Clean up the virtual terminal system, in anticipation for a return to @@ -193,16 +222,17 @@ static void sane_vtputc( unicode_t c) { vtcol += 1 ; } -static void vtputc( unicode_t c) { +static void vtputuc( unicode_t c) { /* In case somebody passes us a signed char.. */ - if( c > 0x10FFFF) /* Let's assume this is due to sign extension */ - c &= 0xFF ; +// if( c > 0x10FFFF) /* Let's assume this is due to sign extension */ +// c &= 0xFF ; + assert( c <= 0x10FFFF) ; - if( c == '\t') - do { + if( c == '\t') { + sane_vtputc( viewtab ? 0xBB : ' ') ; /* 0xBB: '»' */ + while( ((vtcol + lbound) % tabwidth) != 0) sane_vtputc( ' ') ; - } while( ((vtcol + taboff) % tabwidth) != 0) ; - else if( c < 0x20 || c == 0x7F) { + } else if( c < 0x20 || c == 0x7F) { sane_vtputc( '^') ; sane_vtputc( c ^ 0x40) ; } else if( c >= 0x80 && c <= 0xA0) { @@ -224,7 +254,7 @@ static int vtputs( const char *s) { unicode_t c ; s += utf8_to_unicode( s, 0, 4, &c) ; - vtputc( c) ; + vtputuc( c) ; n += utf8_width( c) ; } @@ -242,11 +272,11 @@ static void vteeol( void) { vcp[ vtcol++] = ' ' ; } -/* upscreen: +/* upscreen(): * user routine to force a screen update * always finishes complete update */ -BINDABLE( upscreen) { +TBINDABLE( upscreen) { update( TRUE) ; return TRUE ; } @@ -264,23 +294,27 @@ static int scrflags ; boolean force_f ; force update past type ahead? */ -boolean update( boolean force_f) { +void update( boolean force_f) { + window_p wp ; + #if TYPEAH && ! PKCODE if( force_f == FALSE && typahead()) - return TRUE ; + return ; #endif #if VISMAC == 0 if( force_f == FALSE && kbdmode == PLAY) - return TRUE ; + return ; #endif +#if SIGWINCH displaying = TRUE ; +resize: +#endif #if SCROLLCODE /* first, propagate mode line changes to all instances of a buffer displayed * in more than one window */ - window_p wp ; for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) if( wp->w_flag & WFMODE && wp->w_bufp->b_nwnd > 1) @@ -318,11 +352,6 @@ boolean update( boolean force_f) { /* recalc the current hardware cursor location */ updpos() ; -#if MEMMAP && ! SCROLLCODE - /* update the cursor and flush the buffers */ - movecursor( currow, curcol - lbound) ; -#endif - /* check for lines to de-extend */ upddex() ; @@ -336,12 +365,15 @@ boolean update( boolean force_f) { /* update the cursor and flush the buffers */ movecursor( currow, curcol - lbound) ; TTflush() ; - displaying = FALSE ; #if SIGWINCH - while( chg_width || chg_height) + if( chg_width || chg_height) { newscreensize( chg_height, chg_width) ; + force_f = TRUE ; + goto resize ; + } + + displaying = FALSE ; #endif - return TRUE ; } @@ -438,8 +470,10 @@ static void show_line( line_p lp) { while( i < len) { unicode_t c ; i += utf8_to_unicode( lp->l_text, i, len, &c) ; - vtputc( c) ; + vtputuc( c) ; } + + vteeol() ; } @@ -449,9 +483,10 @@ static void show_line( line_p lp) { * window_p wp; window to update current line in */ static void updone( window_p wp) { + line_p lp ; + /* search down the line we want */ int sline = wp->w_toprow ; /* physical screen line to update */ - line_p lp ; for( lp = wp->w_linep ; lp != wp->w_dotp ; lp = lforw( lp)) ++sline ; @@ -464,7 +499,6 @@ static void updone( window_p wp) { vscreen[ sline]->v_rfcolor = wp->w_fcolor ; vscreen[ sline]->v_rbcolor = wp->w_bcolor ; #endif - vteeol() ; } @@ -486,14 +520,14 @@ static void updall( window_p wp) { /* if we are not at the end */ show_line( lp) ; lp = lforw( lp) ; - } + } else + vteeol() ; /* on to the next one */ #if COLOR vscreen[ sline]->v_rfcolor = wp->w_fcolor ; vscreen[ sline]->v_rbcolor = wp->w_bcolor ; #endif - vteeol() ; ++sline ; } } @@ -504,13 +538,12 @@ static void updall( window_p wp) { This is the only update for simple moves. */ static void updpos( void) { + line_p lp ; + /* find the current row */ - line_p lp = curwp->w_linep ; currow = curwp->w_toprow ; - while( lp != curwp->w_dotp) { + for( lp = curwp->w_linep ; lp != curwp->w_dotp ; lp = lforw( lp)) ++currow ; - lp = lforw( lp) ; - } /* find the current column */ curcol = 0 ; @@ -551,7 +584,6 @@ static void upddex( void) { || (curcol < term.t_ncol - 1)) { vtmove( i, 0) ; show_line( lp) ; - vteeol() ; /* this line no longer is extended */ vscreen[ i]->v_flag &= ~VFEXT ; @@ -572,18 +604,14 @@ static void upddex( void) { static void updgar( void) { for( int i = 0 ; i < term.t_nrow ; ++i) { vscreen[ i]->v_flag |= VFCHG ; -#if REVSTA vscreen[ i]->v_flag &= ~VFREV ; -#endif #if COLOR vscreen[ i]->v_fcolor = gfcolor ; vscreen[ i]->v_bcolor = gbcolor ; #endif -#if MEMMAP == 0 || SCROLLCODE unicode_t *txt = pscreen[ i]->v_text ; for( int j = 0 ; j < term.t_ncol ; ++j) txt[ j] = ' ' ; -#endif } movecursor( 0, 0) ; /* Erase the screen. */ @@ -601,7 +629,7 @@ static void updgar( void) { * * int force; forced update flag */ -static boolean updupd( boolean force_f) { +static void updupd( boolean force_f) { #if SCROLLCODE if( scrflags & WFKILLS) scrolls( FALSE) ; @@ -613,23 +641,15 @@ static boolean updupd( boolean force_f) { #endif for( int i = 0 ; i < term.t_nrow ; ++i) { - video_p vp1 = vscreen[ i] ; - /* for each line that needs to be updated */ - if( (vp1->v_flag & VFCHG) != 0) { + if( (vscreen[ i]->v_flag & VFCHG) != 0) { #if TYPEAH && ! PKCODE if( force_f == FALSE && typahead()) return TRUE ; #endif -#if MEMMAP && ! SCROLLCODE - updateline( i, vp1) ; -#else - updateline( i, vp1, pscreen[ i]) ; -#endif + updateline( i) ; } } - - return TRUE ; } #if SCROLLCODE @@ -731,12 +751,10 @@ static int scrolls( int inserts) { vpp->v_flag = vpv->v_flag ; /* XXX */ if( vpp->v_flag & VFREV) { vpp->v_flag &= ~VFREV ; - vpp->v_flag |= ~VFREQ ; + vpp->v_flag |= VFREQ ; } -#if MEMMAP - vscreen[ to + i]->v_flag &= ~VFCHG ; -#endif } + if( inserts) { from = target ; to = match ; @@ -744,7 +762,7 @@ static int scrolls( int inserts) { from = target + count ; to = match + count ; } -#if MEMMAP == 0 + for( i = from ; i < to ; i++) { unicode_t *txt ; txt = pscreen[ i]->v_text ; @@ -752,9 +770,10 @@ static int scrolls( int inserts) { txt[ j] = ' ' ; vscreen[ i]->v_flag |= VFCHG ; } -#endif + return TRUE ; } + return FALSE ; } @@ -791,30 +810,20 @@ static int endofline( unicode_t *s, int n) { /* updext: - * update the extended line which the cursor is currently - * on at a column greater than the terminal width. The line - * will be scrolled right or left to let the user see where - * the cursor is + update the extended line which the cursor is currently on at a column + greater than the terminal width. The line will be scrolled right or + left to let the user see where the cursor is. */ static void updext( void) { - int rcursor ; /* real cursor location */ - line_p lp ; /* pointer to current line */ - /* calculate what column the real cursor will end up in */ - rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin ; - taboff = lbound = curcol - rcursor + 1 ; + lbound = curcol - ((curcol - term.t_ncol) % term.t_scrsiz + term.t_margin) ; /* scan through the line outputing characters to the virtual screen */ /* once we reach the left edge */ vtmove( currow, -lbound) ; /* start scanning offscreen */ - lp = curwp->w_dotp ; /* line to output */ - show_line( lp) ; + show_line( curwp->w_dotp) ; - /* truncate the virtual line, restore tab offset */ - vteeol() ; - taboff = 0 ; - - /* and put a '$' in column 1 */ + /* put a '$' in column 1 */ vscreen[ currow]->v_text[ 0] = '$' ; } @@ -823,114 +832,62 @@ static void updext( void) { * character sequences; we are using VT52 functionality. Update the physical * row and column variables. It does try an exploit erase to end of line. */ -#if MEMMAP -/* UPDATELINE specific code for the IBM-PC and other compatables */ - -static int updateline( int row, video_p vp1, video_p vp2) { -#if SCROLLCODE - unicode_t *cp1 ; - unicode_t *cp2 ; - int nch ; - - cp1 = &vp1->v_text[ 0] ; - cp2 = &vp2->v_text[ 0] ; - nch = term.t_ncol ; - do { - *cp2 = *cp1 ; - ++cp2 ; - ++cp1 ; - } - while( --nch) ; -#endif -#if COLOR - scwrite( row, vp1->v_text, vp1->v_rfcolor, vp1->v_rbcolor) ; - vp1->v_fcolor = vp1->v_rfcolor ; - vp1->v_bcolor = vp1->v_rbcolor ; -#else - if( vp1->v_flag & VFREQ) - scwrite( row, vp1->v_text, 0, 7) ; - else - scwrite( row, vp1->v_text, 7, 0) ; -#endif - vp1->v_flag &= ~(VFCHG | VFCOL) ; /* flag this line as changed */ -} - -#else /* updateline() * * int row ; row of screen to update - * video_p vp1 ; virtual screen image - * video_p vp2 ; physical screen image */ -static int updateline( int row, video_p vp1, video_p vp2) { -/* UPDATELINE code for all other versions */ - - unicode_t *cp1 ; - unicode_t *cp2 ; - unicode_t *cp3 ; - unicode_t *cp4 ; - unicode_t *cp5 ; - int nbflag ; /* non-blanks to the right flag? */ -#if REVSTA - int rev ; /* reverse video flag */ -#endif - int req = FALSE ; /* reverse video request flag */ - +static void updateline( int row) { + video_p vp1 = vscreen[ row] ; + vp1->v_flag &= ~VFCHG ; /* flag this line as updated */ /* set up pointers to virtual and physical lines */ - cp1 = &vp1->v_text[ 0] ; - cp2 = &vp2->v_text[ 0] ; + unicode_t *inp = vp1->v_text ; + unicode_t *out = pscreen[ row]->v_text ; #if COLOR TTforg( vp1->v_rfcolor) ; TTbacg( vp1->v_rbcolor) ; #endif -#if REVSTA | COLOR - /* do a re-write of the entire line if it is reverse or there - ** is a request to change the reverse status */ - rev = (vp1->v_flag & VFREV) == VFREV ; - req = (vp1->v_flag & VFREQ) == VFREQ ; - if( req || (req != rev) +/* do a re-write of the entire line if there is a request to toggle the + * reverse status */ + int rev = (vp1->v_flag & VFREV) == VFREV ; + if( rev != ((vp1->v_flag & VFREQ) == VFREQ) #if COLOR - || (vp1->v_fcolor != vp1->v_rfcolor) - || (vp1->v_bcolor != vp1->v_rbcolor) + || (vp1->v_fcolor != vp1->v_rfcolor) + || (vp1->v_bcolor != vp1->v_rbcolor) #endif - ) { + ) { movecursor( row, 0) ; /* Go to start of line. */ - TTrev( req) ; /* set needed rev video state */ + TTrev( !rev) ; /* set needed rev video state */ /* scan through the line and dump it to the screen and the virtual screen array */ while( ttcol < term.t_ncol) { /* TODO: handle double width unicode char at last screen col */ - unicode_t c = *cp1++ ; + unicode_t c = *out++ = *inp++ ; TTputc( c) ; - ttcol += utf8_width( c) ; - *cp2++ = c ; + ttcol += _utf8_width( c) ; /* filtered by vtputuc */ } TTrev( FALSE) ; /* turn rev video off */ /* update the needed flags */ - vp1->v_flag &= ~VFCHG ; - if( req) - vp1->v_flag |= VFREV ; - else - vp1->v_flag &= ~VFREV ; + vp1->v_flag ^= VFREV ; #if COLOR vp1->v_fcolor = vp1->v_rfcolor ; vp1->v_bcolor = vp1->v_rbcolor ; #endif - return TRUE ; + return ; } -#endif /* advance past any common chars at the left */ - while( cp1 != &vp1->v_text[ term.t_ncol] && cp1[ 0] == cp2[ 0]) { - ++cp1 ; - ++cp2 ; + unicode_t *end = &vp1->v_text[ term.t_ncol] ; + int startcol = 0 ; + while( inp != end && *inp == *out) { + startcol += _utf8_width( *inp++) ; /* filtered by vtputuc */ + ++out ; } /* This can still happen, even though we only call this routine on changed @@ -940,97 +897,72 @@ static int updateline( int row, video_p vp1, video_p vp2) { * be hard operations that do a lot of update, so I don't really care. */ /* if both lines are the same, no update needs to be done */ - if( cp1 == &vp1->v_text[ term.t_ncol]) { - vp1->v_flag &= ~VFCHG ; /* flag this line is changed */ - return TRUE ; - } + if( inp == end) + return ; /* find out if there is a match on the right */ - nbflag = FALSE ; - cp3 = &vp1->v_text[ term.t_ncol] ; - cp4 = &vp2->v_text[ term.t_ncol] ; + int nbflag = FALSE ; /* non-blanks to the right flag? */ - while( cp3[ -1] == cp4[ -1]) { - --cp3 ; - --cp4 ; - if( cp3[ 0] != ' ') /* Note if any nonblank */ + unicode_t *nbp = &pscreen[ row]->v_text[ term.t_ncol] ; + while( end[ -1] == nbp[ -1]) { + --end ; + --nbp ; + if( *end != ' ') /* Note if any nonblank */ nbflag = TRUE ; /* in right match. */ } - cp5 = cp3 ; + nbp = end ; /* Erase to EOL ? */ - if( nbflag == FALSE && eolexist == TRUE && (req != TRUE)) { - while( cp5 != cp1 && cp5[ -1] == ' ') - --cp5 ; + if( nbflag == FALSE && eolexist == TRUE && (rev != TRUE)) { + while( nbp != inp && nbp[ -1] == ' ') + --nbp ; - if( cp3 - cp5 <= 3) /* Use only if erase is */ - cp5 = cp3 ; /* fewer characters. */ + if( end - nbp <= 3) /* Use only if erase is */ + nbp = end ; /* fewer characters. */ } - movecursor( row, cp1 - &vp1->v_text[ 0]) ; /* Go to start of line. */ -#if REVSTA + movecursor( row, startcol) ; /* Go to start of line change */ TTrev( rev) ; -#endif - while( cp1 != cp5) { /* Ordinary. */ - unicode_t c = *cp1++ ; + while( inp != nbp) { /* Copy */ + unicode_t c = *out++ = *inp++ ; TTputc( c) ; ttcol += utf8_width( c) ; - *cp2++ = c ; } - if( cp5 != cp3) { /* Erase. */ + if( inp != end) { /* Erase */ TTeeol() ; - while( cp1 != cp3) - *cp2++ = *cp1++ ; + do + *out++ = ' ' ; + while( ++inp != end) ; } -#if REVSTA + TTrev( FALSE) ; -#endif - vp1->v_flag &= ~VFCHG ; /* flag this line as updated */ - return TRUE ; } -#endif -/* Redisplay the mode line for the window pointed to by the "wp". This is the - * only routine that has any idea of how the modeline is formatted. You can - * change the modeline format by hacking at this routine. Called by "update" - * any time there is a dirty window. +/* Redisplay the mode line for the window pointed to by the "wp". This is + the only routine that has any idea of how the modeline is formatted. + You can change the modeline format by hacking at this routine. Called + by "update" any time there is a dirty window. */ static void modeline( window_p wp) { - int n ; /* cursor position count */ - buffer_p bp ; - int i ; /* loop index */ - int lchar ; /* character to draw line in buffer with */ - int firstm ; /* is this the first mode? */ + char tline[] = " % " ; /* formatting buffer for percentage */ - n = wp->w_toprow + wp->w_ntrows ; /* Location. */ + int n = wp->w_toprow + wp->w_ntrows ; /* Location. */ vscreen[ n]->v_flag |= VFCHG | VFREQ | VFCOL ; /* Redraw next time. */ #if COLOR vscreen[ n]->v_rfcolor = 0 ; /* black on */ vscreen[ n]->v_rbcolor = 7 ; /* white..... */ #endif vtmove( n, 0) ; /* Seek to right line. */ - if( wp == curwp) /* mark the current buffer */ -#if PKCODE && REVSTA - lchar = '-' ; -#else - lchar = '=' ; -#endif - else -#if REVSTA - if( revexist) - lchar = ' ' ; - else -#endif - lchar = '-' ; + int lchar = "-= -"[ 2 * revexist + (wp == curwp)] ; /* pick bg character */ - bp = wp->w_bufp ; - vtputc( ((bp->b_flag & BFTRUNC) != 0) ? '#' : lchar) ; /* truncated? */ - vtputc( ((bp->b_flag & BFCHG) != 0) ? '*' : lchar) ; /* changed? */ - vtputc( ' ') ; + buffer_p bp = wp->w_bufp ; + vtputuc( ((bp->b_flag & BFTRUNC) != 0) ? '#' : lchar) ; /* truncated? */ + vtputuc( ((bp->b_flag & BFCHG) != 0) ? '*' : lchar) ; /* changed? */ + vtputuc( ' ') ; if( n == term.t_nrow - 1) n = 3 + vtputs( PROGRAM_NAME_UTF8 " " VERSION ": ") ; @@ -1040,105 +972,75 @@ static void modeline( window_p wp) { n += vtputs( bp->b_bname) ; n += vtputs( " (") ; - /* display the modes */ - - if( (bp->b_flag & BFTRUNC) != 0) { - firstm = FALSE ; +/* display the modes */ + int pos = n ; + if( (bp->b_flag & BFTRUNC) != 0) n += vtputs( "Truncated") ; - } else - firstm = TRUE ; - for( i = 0 ; i < NUMMODES ; i++) /* add in the mode flags */ + for( int i = 0 ; i < NUMMODES ; i++) /* add in the mode flags */ if( wp->w_bufp->b_mode & (1 << i)) { - if( firstm != TRUE) - n += vtputs( " ") ; - else - firstm = FALSE ; + if( n > pos) { + vtputuc( ' ') ; + n += 1 ; + } n += vtputs( modename[ i]) ; } n += vtputs( ") ") ; -#if PKCODE if( bp->b_fname[ 0] != 0 && strcmp( bp->b_bname, bp->b_fname) != 0) { -#else - if( bp->b_fname[ 0] != 0) { /* File name. */ - n += vtputs( "File: ") ; -#endif n += vtputs( bp->b_fname) ; - vtputc(' ') ; + vtputuc( ' ') ; ++n ; } while( n < term.t_ncol) { /* Pad to full width. */ - vtputc( lchar) ; + vtputuc( lchar) ; ++n ; } - { /* determine if top line, bottom line, or both are visible */ - line_p lp = wp->w_linep ; - int rows = wp->w_ntrows ; - char *msg = NULL ; - char tline[ 6] ; /* buffer for part of mode line */ +/* determine if top line, bottom line, or both are visible */ + char *msg = NULL ; - vtcol -= 7 ; /* strlen(" top ") plus a couple */ - while( rows--) { + if( wp->w_linep == wp->w_bufp->b_linep) + msg = "Empty" ; + else { + if( lback( wp->w_linep) == wp->w_bufp->b_linep) + msg = " Top " ; + + line_p lp = wp->w_linep ; + for( int rows = wp->w_ntrows ; rows > 0 ; rows--) { lp = lforw( lp) ; if( lp == wp->w_bufp->b_linep) { - msg = " Bot " ; + msg = msg ? " All " : " End " ; break ; } } - if( lback( wp->w_linep) == wp->w_bufp->b_linep) { - if( msg) { - if( wp->w_linep == wp->w_bufp->b_linep) - msg = " Emp " ; - else - msg = " All " ; - } else { - msg = " Top " ; - } - } + if( !msg) { - line_p lp ; - int numlines, predlines ; - - lp = lforw( bp->b_linep) ; - numlines = 0 ; - predlines = 0 ; - while( lp != bp->b_linep) { - if( lp == wp->w_linep) { - predlines = numlines ; - } - ++numlines ; - lp = lforw( lp) ; + /* buffer is not empty, both first and last line not in window */ + n = 0 ; /* count of lines in buffer */ + pos = 0 ; /* line number of the top line in window */ + for( lp = lforw( bp->b_linep) ; lp != bp->b_linep ; + lp = lforw( lp)) { + n += 1 ; + if( lp == wp->w_linep) + pos = n ; } - if( wp->w_dotp == bp->b_linep) { - msg = " Bot " ; - } else { - int ratio = 0 ; - if( numlines != 0) - ratio = (100L * predlines) / numlines ; - if( ratio > 99) - ratio = 99 ; + pos = (100L * pos) / n ; + tline[ 2] = pos % 10 + '0' ; + pos /= 10 ; + if( pos) + tline[ 1] = pos + '0' ; - tline[ 0] = ' ' ; - tline[ 1] = ratio / 10 + '0' ; - tline[ 2] = ratio % 10 + '0' ; - tline[ 3] = '%' ; - tline[ 4] = ' ' ; - tline[ 5] = 0 ; - if( tline[ 1] == '0') - tline[ 1] = ' ' ; - - msg = tline ; - } + msg = tline ; } - - n += vtputs( msg) ; } + + vtcol -= 7 ; /* strlen(" top ") plus a couple */ + vtputs( msg) ; } void upmode( void) { /* update all the mode lines */ @@ -1402,7 +1304,7 @@ void getscreensize( int *widthp, int *heightp) { } #ifdef SIGWINCH -void sizesignal( int signr) { +static void sizesignal( int signr) { int w, h ; int old_errno = errno ; @@ -1411,33 +1313,37 @@ void sizesignal( int signr) { if( h > 0 && w > 0) { term.t_mrow = h = h < term.t_maxrow ? h : term.t_maxrow ; term.t_mcol = w = w < term.t_maxcol ? w : term.t_maxcol ; - if( h - 1 != term.t_nrow || w != term.t_ncol) - newscreensize( h, w) ; + if( h - 1 != term.t_nrow || w != term.t_ncol) { + if( displaying) { + chg_width = w ; + chg_height = h ; + } else { + newscreensize( h, w) ; + update( TRUE) ; + } + } } signal( SIGWINCH, sizesignal) ; errno = old_errno ; } -static int newscreensize( int h, int w) { -/* do the change later */ - if( displaying) { - chg_width = w ; - chg_height = h ; - return FALSE ; - } - +static void newscreensize( int h, int w) { chg_width = chg_height = 0 ; + vtfree() ; + if( h < MINROWS) + h = MINROWS ; + + if( w < MINCOLS) + w = MINCOLS ; + + vtalloc( h, w) ; if( h <= term.t_mrow) newsize( TRUE, h) ; if( w <= term.t_mcol) newwidth( TRUE, w) ; - - update( TRUE) ; - return TRUE ; } - #endif diff --git a/display.h b/display.h index 89371fd..3d10af8 100644 --- a/display.h +++ b/display.h @@ -4,10 +4,13 @@ #include -#include "estruct.h" +#include "defines.h" /* UNIX */ #include "names.h" /* BINDABLE() */ #include "utf8.h" /* unicode_t */ +#define MINROWS 3 +#define MINCOLS 10 + extern int mpresf ; /* Stuff in message line */ extern int scrollcount ; /* number of lines to scroll */ extern int discmd ; /* display command flag */ @@ -15,13 +18,17 @@ extern int disinp ; /* display input characters (echo) */ extern int gfcolor ; /* global forgrnd color (white) */ extern int gbcolor ; /* global backgrnd color (black) */ +/* global variables */ +extern boolean viewtab ; /* $viewtab = TRUE to visualize hardcoded tab */ + /* Bindable functions */ -BINDABLE( upscreen) ; +TBINDABLE( upscreen) ; void vtinit( void) ; void vtfree( void) ; void vttidy( void) ; -boolean update( boolean force_f) ; +void update( boolean force_f) ; +void updmargin( void) ; void upmode( void) ; void movecursor( int row, int col) ; void mlerase( void) ; @@ -37,8 +44,6 @@ void getscreensize( int *widthp, int *heightp) ; # include # ifdef SIGWINCH extern int chg_width, chg_height ; - - void sizesignal( int signr) ; # endif #endif diff --git a/emacs.hlp b/emacs.hlp index 7f9ff80..7dcbf20 100644 --- a/emacs.hlp +++ b/emacs.hlp @@ -19,7 +19,7 @@ ------------------------------------------------------------------------------- => THE VERY BASICS Notations: ^X means and X. The key is on most systems. -Exiting: ^G aborts almost any operation. ^X ^C will get you out of uEmacs. +Exiting: ^G aborts almost any operation. ^X ^C will get you out of µEMACS. A BUFFER is a named area containing a FILE being edited. Many buffers may be active at once. Many WINDOWS may be active at once on the screen. All @@ -37,7 +37,7 @@ Beginning of file ..... Meta < End of file ........... Meta > ------------------------------------------------------------------------------- => FILE COMMANDS Find file ............. ^X ^F Quick exit ............ Meta Z -View file ............. ^X ^V Exit emacs ............ ^X ^C +View file ............. ^X ^V Exit µEMACS ........... ^X ^C Insert file ........... ^X ^I Change file name ...... ^X N Filter buffer ......... ^X # Save file ............. ^X ^D @@ -118,12 +118,12 @@ Query replace string .. Meta ^R :: Yes/no Y/N, replace rest !, cancel ^G. ------------------------------------------------------------------------------- => ACCESSING THE OPERATING SYSTEM Quick exit ............ Meta Z :: Write out all changed buffers and exit. -Exit emacs ............ ^X ^C :: Exit without automatic save. +Exit µEMACS ........... ^X ^C :: Exit without automatic save. I shell ............... ^X C :: Start a new command processor. Shell command ......... ^X ! :: Execute one operating system command. -Pipe command .......... ^X @ :: Pipe command results to a new buffer. * -Filter buffer ......... ^X # :: Filter buffer through a program. * -Execute program ....... ^X $ :: * Not under VMS. +Pipe command .......... ^X @ :: Pipe command results to a new buffer. +Filter buffer ......... ^X # :: Filter buffer through a program. +Execute program ....... ^X $ :: ------------------------------------------------------------------------------- => MACRO COMMANDS Begin macro ........... ^X ( diff --git a/emacs.rc b/emacs.rc index b16212f..339feee 100644 --- a/emacs.rc +++ b/emacs.rc @@ -1,113 +1,51 @@ -; EMACS.RC / .emacsrc +; .emacsrc -- Startup file for µEMACS 4.2 ; -; Startup file for MicroEMACS 3.9 and uEmacs/PK 4.0 ; This file is executed every time the editor is entered. -; -; Modified by Petri Kutvonen, last edited September 1991. -set $discmd "FALSE" +set $discmd FALSE +!if ¬ &seq $progname µEMACS +; uemacs/PK and MicroEMACS + set $discmd TRUE + !return +!endif -!if &seq $progname "µEMACS" - !force execute-file &cat $HOME "/.uerc" +set $tab 4 +# set $viewtab TRUE # uncomment this line if you need to visualize tabs +set $fillcol 76 + + +## Help facility +!if &seq $TERM cygwin + set $scroll FALSE + set %F1 FNP #currently not readable + set %Home FN1 + set %End FN4 !else - -; First, try to resolve if we are on a PC ... yes, this is a kludge - -!if &seq $sres "NORMAL" - set %system "OTHER" -!else - set %system "PC" + set %F1 FNP + set %Home FNH + set %End FNF !endif -!if &seq %system "PC" - -; PC specific initialization - -write-message "(Setting up)" - -; Comment out or change this line if you want more than 25 lines, -; other possible $sres values include EGA and VGA - -set $sres "CGA" - -; Uncomment next line if your old screen "snows" - -;set $flicker "TRUE" - -; If your screen "snows" you'll not like scrolling - -!if &seq $flicker "TRUE" - set $scroll "FALSE" -!endif - -; Function keys (unshifted) -; f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 -; FN; FN< FN= FN> FN? FN@ FNA FNB FNC FND - -bind-to-key help FN; -bind-to-key exit-emacs FND - -; Function keys (shifted) -; F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 -; FNT FNU FNV FNW FNX FNY FNZ FN[ FN\ FN] - -; Other special keys (unshifted) -; Home End Ins Del PgUp PgDn -; FNG FNO FNR FNS FNI FNQ - -; Some common Alt-keys -; Alt-X Alt-Z Alt-C Alt-F Alt-O -; FN- FN, FN. FN! FN^X - -bind-to-key exit-emacs FN- -bind-to-key quick-exit FN, -bind-to-key i-shell FN. -bind-to-key find-file FN! -bind-to-key view-file FN/ -bind-to-key next-window FN^X - -; Set screen colors - -; You can define a DOS environment variable EMACS_BW (any value) -; if you don't like colors, e.g. if you have a LCD screen - -!if &seq &env "EMACS_BW" "" - add-global-mode "blue" - add-global-mode "HIGH" -!endif - -!endif - -; Help facility - -40 store-macro - set $discmd "FALSE" +!store 40 + set $discmd FALSE !if ¬ &seq $cbufname "emacs.hlp" write-message "(Loading Help)" !force help - !force 8 resize-window - !if &seq %system "PC" - !if &seq &env "EMACS_BW" "" - add-mode "red" - !endif - bind-to-key execute-macro-38 FNI - bind-to-key execute-macro-37 FNQ + !if ¬ &seq $cbufname "emacs.hlp" + write-message "(Failed to load Help)" !else - bind-to-key execute-macro-38 FN5 - bind-to-key execute-macro-37 FN6 + !force 8 resize-window + bind-to-key execute-macro-39 FN5 + bind-to-key execute-macro-38 FN6 + bind-to-key execute-macro-37 %Home + bind-to-key execute-macro-36 %End + beginning-of-line + 2 forward-character + 1 redraw-display + set %hlpupdn "[PgUp] / [PgDn]" + set %hlphelp "[F1]" + run helponhelp !endif - beginning-of-line - 2 forward-character - 1 redraw-display - save-window - !if &seq %system "PC" - set %hlpupdn " / " - set %hlphelp "" - !else - set %hlpupdn " / " - set %hlphelp "" - !endif - execute-macro-39 !else set %hlpcode &lef $line 2 !if &seq %hlpcode ".." @@ -117,33 +55,29 @@ bind-to-key next-window FN^X beginning-of-line 2 forward-character 1 redraw-display - execute-macro-39 + run helponhelp !else - !if &seq %system "PC" - bind-to-key previous-page FNI - bind-to-key next-page FNQ - !else - bind-to-key previous-page FN5 - bind-to-key next-page FN6 - !endif - !force restore-window + !force search-reverse "=>" + bind-to-key previous-page FN5 + bind-to-key next-page FN6 + bind-to-key beginning-of-file %Home + bind-to-key end-of-file %End !force delete-window clear-message-line !endif !endif - set $discmd "TRUE" + set $discmd TRUE !endm bind-to-key execute-macro-40 M-? -!if &seq %system "PC" - bind-to-key execute-macro-40 FN; -!else - bind-to-key execute-macro-40 FNh -!endif +bind-to-key execute-macro-40 %F1 +bind-to-key execute-macro-40 M-O +bind-to-key beginning-of-file %Home +bind-to-key end-of-file %End -; Help on Help -39 store-macro +## Help on Help +!store helponhelp !if &seq &rig $line 5 "INDEX" write-message &cat "Select topic from list and press " %hlphelp !else @@ -151,150 +85,72 @@ bind-to-key execute-macro-40 M-? !endif !endm -; Previous help page -38 store-macro +## Previous help page +!store 39 !if &seq $cbufname "emacs.hlp" beginning-of-line !force search-reverse "=>" 2 forward-character 1 redraw-display - execute-macro-39 + run helponhelp !else previous-page !endif !endm -; Next help page -37 store-macro +## Next help page +!store 38 !if &seq $cbufname "emacs.hlp" beginning-of-line 2 forward-character !force search-forward "=>" 1 redraw-display - execute-macro-39 + run helponhelp !else next-page !endif !endm -; Set up auto CMODE +!store 37 + beginning-of-file + !if &seq $cbufname "emacs.hlp" + execute-macro-39 + !endif +!endm -36 store-macro - !if &seq &mid $cfname 1 7 "/tmp/Re" - add-mode "wrap" - !return - !endif - !if &gre &sin $cfname "/.ed" 0 - add-mode "wrap" - !return - !endif - !if &gre &sin $cfname "/.let" 0 - add-mode "wrap" - !return - !endif - !if &gre &sin $cfname "/.art" 0 - add-mode "wrap" - !return - !endif - !if &gre &sin $cfname "/nn." 0 - add-mode "wrap" - !return - !endif - set %rctmp &sin $cfname "." - !if &equ %rctmp 0 - !return - !endif - set %rctmp &mid $cfname &add %rctmp 1 5 - !if &or &seq %rctmp "c" &seq %rctmp "h" - add-mode "cmode" - !endif - !if &or &seq %rctmp "txt" &or &seq %rctmp "doc" &or &seq %rctmp "tmp" &seq %rctmp "tex" - add-mode "wrap" +!store 36 + end-of-file + !if &seq $cbufname "emacs.hlp" + execute-macro-39 !endif +!endm + +## Set up auto CMODE or WRAP +!store 35 + set %rctmp &right $cfname 4 + !if &or &seq .txt %rctmp &seq .doc %rctmp + add-mode wrap + !return + !endif + set %rctmp &right %rctmp 2 + !if &or &seq .c %rctmp &seq .h %rctmp + add-mode cmode + !return + !endif !endm -bind-to-key execute-macro-36 M-FNR +bind-to-key execute-macro-35 M-FNR -; Setup for ASCII {|}[\] to ISO Latin-1 translation - -21 store-macro - insert-string "" -!endm -22 store-macro - insert-string "" -!endm -23 store-macro - insert-string "" -!endm -24 store-macro - insert-string "" -!endm -25 store-macro - insert-string "" -!endm -26 store-macro - insert-string "" -!endm - -27 store-macro - bind-to-key execute-macro-21 { - bind-to-key execute-macro-22 | - bind-to-key execute-macro-23 } - bind-to-key execute-macro-24 [ - bind-to-key execute-macro-25 \ - bind-to-key execute-macro-26 ] - write-message "ISO Latin-1 " -!endm - -28 store-macro - unbind-key { - unbind-key | - unbind-key } - unbind-key [ - unbind-key \ - unbind-key ] - write-message "ASCII {|}[\]" -!endm - -bind-to-key execute-macro-27 ^X[ -bind-to-key execute-macro-28 ^X] - -; Make cut-paste easier in window systems +## Make cut-paste easier in window systems bind-to-key newline ^J -; uEmacs/PK specific initialization -!if &seq $progname "uEmacs/PK" - -; Don't scroll on a Sun - - !if &or &seq $TERM "sun" &seq $TERM "sun-cmd" - set $scroll "FALSE" - !endif - -; Execute local initialization files - - !if &seq %system "PC" - !force execute-file "EM.RC" - !else - !force execute-file &cat $HOME "/.emrc" - !force execute-file ".emrc" - !endif -!endif - -!if &gre &sin $LANG "UTF-8" 0 +!if &or &sin $LANG "UTF-8" &sin $LANG "utf8" add-global-mode "utf-8" !endif -!if &gre &sin $LANG "utf8" 0 - add-global-mode "utf-8" -!endif -add-global-mode "utf-8" - -!endif - -set $discmd "TRUE" +set $discmd TRUE diff --git a/estruct.h b/estruct.h deleted file mode 100644 index 1de6331..0000000 --- a/estruct.h +++ /dev/null @@ -1,135 +0,0 @@ -/* estruct.h -- */ -#ifndef _ESTRUCT_H_ -#define _ESTRUCT_H_ - -/* Structure and preprocessor defines - * - * written by Dave G. Conroy - * modified by Steve Wilhite, George Jones - * substantially modified by Daniel Lawrence - * modified by Petri Kutvonen - */ - -#ifdef MSDOS -# undef MSDOS -#endif - -/* Machine/OS definitions. */ - -#if defined(AUTOCONF) || defined(BSD) || defined(SYSV) - -/* Make an intelligent guess about the target system. */ - -# if defined(BSD) || defined(sun) || defined(ultrix) || defined(__osf__) -# ifndef BSD -# define BSD 1 /* Berkeley UNIX */ -# endif -# else -# define BSD 0 -# endif - -# if defined(SVR4) || defined(__linux__) /* ex. SunOS 5.3 */ -# define SVR4 1 -# define SYSV 1 -# undef BSD -# endif - -# if defined(SYSV) || defined(u3b2) || defined(_AIX) || (defined(i386) && defined(unix)) || defined( __unix__) -# define USG 1 /* System V UNIX */ -# else -# define USG 0 -# endif - -#else -# define BSD 0 /* UNIX BSD 4.2 and ULTRIX */ -# define USG 1 /* UNIX system V */ -#endif /*autoconf || BSD || SYSV */ - -#define MSDOS 0 /* MS-DOS */ - -/* Compiler definitions */ -#ifndef AUTOCONF -# define UNIX 1 /* a random UNIX compiler */ -#else -# define UNIX (BSD | USG) -#endif /*autoconf */ - -/* Debugging options */ - -#define RAMSIZE 0 /* dynamic RAM memory usage tracking */ -#if RAMSIZE -# define RAMSHOW 1 /* auto dynamic RAM reporting */ -#endif - -#ifndef AUTOCONF -/* Terminal Output definitions */ -# define TERMCAP 0 /* Use TERMCAP */ -# define IBMPC 1 /* IBM-PC CGA/MONO/EGA driver */ -#else -# define TERMCAP UNIX -# define IBMPC MSDOS -#endif /* Autoconf. */ - -/* Configuration options */ - -#define VISMAC 0 /* update display during keyboard macros */ - -#ifndef AUTOCONF -# define COLOR 1 /* color commands and windows */ -# define FILOCK 0 /* file locking under unix BSD 4.2 */ -#else -# define COLOR MSDOS -# ifdef SVR4 -# define FILOCK 1 -# else -# define FILOCK BSD -# endif -#endif /* Autoconf. */ - -#define CLEAN 0 /* de-alloc memory on exit */ - -#ifndef AUTOCONF -# define XONXOFF 0 /* don't disable XON-XOFF flow control P.K. */ -#else -# define XONXOFF UNIX -#endif /* Autoconf. */ - -#define PKCODE 1 /* include my extensions P.K., define always */ -#define SCROLLCODE 1 /* scrolling code P.K. */ - -/* Define some ability flags. */ - -#if IBMPC -# define MEMMAP 1 -#else -# define MEMMAP 0 -#endif - -#if USG | BSD -# define ENVFUNC 1 -#else -# define ENVFUNC 0 -#endif - -/* Dynamic RAM tracking and reporting redefinitions */ - -#if RAMSIZE -# include - void *allocate( size_t size) ; - void release( void *ptr) ; -# define malloc allocate -# define free release -#endif - -/* De-allocate memory always on exit (if the operating system or - main program can not -*/ - -#if CLEAN -# define exit(a) cexit(a) - - void cexit( int status) ; -#endif - -#endif -/* end of estruct.h */ diff --git a/eval.c b/eval.c index c4f427f..ced8549 100644 --- a/eval.c +++ b/eval.c @@ -8,7 +8,6 @@ */ #include -#include #include #include #include @@ -16,8 +15,8 @@ #include "basic.h" #include "bind.h" #include "buffer.h" +#include "defines.h" #include "display.h" -#include "estruct.h" #include "exec.h" #include "execute.h" #include "flook.h" @@ -31,8 +30,6 @@ #include "version.h" #include "window.h" -#define MAXVARS 255 - /* Macro argument token types */ #define TKNUL 0 /* end-of-string */ @@ -47,7 +44,6 @@ #define TKSTR 9 /* quoted string literal */ #define TKCMD 10 /* command name */ -static int gettyp( char *token) ; /* Emacs global flag bit definitions (for gflags). */ /* if GFREAD is set, current buffer will be set on first file (read in) */ @@ -68,17 +64,19 @@ int rval = 0 ; /* return value of a subprocess */ static int saveflag = 0 ; /* Flags, saved with the $target var */ -long envram = 0l ; /* # of bytes current in use by malloc */ +unsigned envram = 0 ; /* # of bytes current in use by malloc */ -/* Max #chars in a var name. */ -#define NVSIZE 10 +/* User variables ******************************************/ +#define MAXVARS 255 +#define NVSIZE 10 /* Max #chars in a var name. */ /* Structure to hold user variables and their definitions. */ -struct user_variable { - char u_name[NVSIZE + 1]; /* name of user variable */ - char *u_value; /* value (string) */ -}; +static struct { + char u_name[ NVSIZE + 1] ; /* name of user variable */ + char *u_value ; /* value (string) */ +} uv[ MAXVARS + 1] ; + static char errorm[] = "ERROR" ; /* error literal */ @@ -129,6 +127,7 @@ static const char *envars[] = { "rval", /* child process return value */ "tab", /* tab width, 1... */ "hardtab", /* TRUE for hard coded tab, FALSE for soft ones */ + "viewtab", /* TRUE to visualize hard coded tabs */ "overlap", "jump", #if SCROLLCODE @@ -136,7 +135,7 @@ static const char *envars[] = { #endif }; -/* And its preprocesor definitions. */ +/* And its preprocessor definitions. */ #define EVFILLCOL 0 #define EVPAGELEN 1 @@ -177,9 +176,10 @@ static const char *envars[] = { #define EVRVAL 36 #define EVTAB 37 #define EVHARDTAB 38 -#define EVOVERLAP 39 -#define EVSCROLLCOUNT 40 -#define EVSCROLL 41 +#define EVVIEWTAB 39 +#define EVOVERLAP 40 +#define EVSCROLLCOUNT 41 +#define EVSCROLL 42 enum function_type { NILNAMIC = 0, @@ -188,6 +188,9 @@ enum function_type { TRINAMIC = (3 << 6) } ; +#define ARGCOUNT( ft) (ft >> 6) +#define FUNID( ft) (ft & ((1 << 6) - 1)) + enum function_code { UFADD = 0, UFSUB, UFTIMES, UFDIV, UFMOD, UFNEG, UFCAT, UFLEFT, UFRIGHT, UFMID, UFNOT, UFEQUAL, @@ -202,7 +205,7 @@ enum function_code { static struct { const char f_name[ 4] ; const int f_type ; -} funcs[] = { +} const funcs[] = { { "abs", UFABS | MONAMIC }, /* absolute value of a number */ { "add", UFADD | DYNAMIC }, /* add two numbers together */ { "and", UFAND | DYNAMIC }, /* logical and */ @@ -212,7 +215,7 @@ static struct { { "bno", UFBNOT | MONAMIC }, /* bitwise not */ { "bor", UFBOR | DYNAMIC }, /* bitwise or 9-10-87 jwm */ { "bxo", UFBXOR | DYNAMIC }, /* bitwise xor 9-10-87 jwm */ - { "cat", UFCAT | DYNAMIC }, /* concatinate string */ + { "cat", UFCAT | DYNAMIC }, /* concatenate string */ { "chr", UFCHR | MONAMIC }, /* integer to char conversion */ { "div", UFDIV | DYNAMIC }, /* division */ { "env", UFENV | MONAMIC }, /* retrieve a system environment var */ @@ -237,7 +240,7 @@ static struct { { "sgr", UFSGREAT | DYNAMIC }, /* string logical greater than */ { "sin", UFSINDEX | DYNAMIC }, /* find the index of one string in another */ { "sle", UFSLESS | DYNAMIC }, /* string logical less than */ - { "sub", UFSUB | DYNAMIC }, /* subtraction */ + { "sub", UFSUB | DYNAMIC }, /* substraction */ { "tim", UFTIMES | DYNAMIC }, /* multiplication */ { "tru", UFTRUTH | MONAMIC }, /* Truth of the universe logical test */ { "upp", UFUPPER | MONAMIC }, /* uppercase string */ @@ -245,21 +248,18 @@ static struct { } ; -/* User variables */ -static struct user_variable uv[MAXVARS + 1]; - /* When emacs' command interpetor needs to get a variable's name, * rather than it's value, it is passed back as a variable description * structure. The v_num field is a index into the appropriate variable table. */ -struct variable_description { - int v_type; /* Type of variable. */ - int v_num; /* Ordinal pointer to variable in list. */ -}; +typedef struct { + int v_type ; /* Type of variable. */ + int v_num ; /* Ordinal pointer to variable in list. */ +} variable_description ; -static void findvar( char *var, struct variable_description *vd, int size) ; -static int svar( struct variable_description *var, char *value) ; -static char *i_to_a( int i) ; +static void findvar( char *var, variable_description *vd, int size) ; +static int svar( variable_description *var, char *value) ; +static const char *i_to_a( int i) ; /* * putctext: @@ -307,25 +307,22 @@ void varinit(void) seed = time( NULL) ; } -/* - * Evaluate a function. + +/* Evaluate a function. * * @fname: name of function to evaluate. */ static const char *gtfun( char *fname) { - unsigned fnum ; /* index to function to eval */ - char *arg1 ; /* value of first argument */ - char *arg2 ; /* value of second argument */ - char *arg3 ; /* last argument */ - const char *retstr ; /* return value */ - int low, high ; /* binary search indexes */ + char *argv[ 3] ; + const char *retstr ; /* return value */ + int i ; - /* look the function up in the function table */ - fname[3] = 0; /* only first 3 chars significant */ - mklower(fname); /* and let it be upper or lower case */ - fnum = ARRAY_SIZE( funcs) ; - low = 0 ; - high = fnum - 1 ; +/* look the function up in the function table */ + fname[ 3] = 0 ; /* only first 3 chars significant */ + mklower( fname) ; /* and let it be upper or lower case */ + unsigned fnum = ARRAY_SIZE( funcs) ; /* index to function to eval */ + int low = 0 ; /* binary search low bound */ + int high = fnum - 1 ; /* binary search high bound */ do { int s, cur ; @@ -340,92 +337,70 @@ static const char *gtfun( char *fname) { low = cur + 1 ; } while( low <= high) ; - /* return errorm on a bad reference */ - if (fnum == ARRAY_SIZE(funcs)) - return errorm; +/* return errorm on a bad reference */ + if( fnum == ARRAY_SIZE( funcs)) + return errorm ; - arg1 = arg2 = arg3 = NULL ; +/* fetch arguments */ assert( clexec == TRUE) ; /* means macarg can be replaced by gettokval */ - /* if needed, retrieve the first argument */ - if (funcs[fnum].f_type >= MONAMIC) { - arg1 = getnewtokval() ; - if( arg1 == NULL) - return errorm; + int argc = ARGCOUNT( funcs[ fnum].f_type) ; + for( int i = 0 ; i < argc ; i++) { + argv[ i] = getnewtokval() ; + if( argv[ i] == NULL) { + while( i > 0) + free( argv[ --i]) ; - /* if needed, retrieve the second argument */ - if (funcs[fnum].f_type >= DYNAMIC) { - arg2 = getnewtokval() ; - if( arg2 == NULL) { - free( arg1) ; - return errorm; - } - - /* if needed, retrieve the third argument */ - if (funcs[fnum].f_type >= TRINAMIC) { - arg3 = getnewtokval() ; - if( arg3 == NULL) { - free( arg1) ; - free( arg2) ; - return errorm; - } - } + return errorm ; } } - /* and now evaluate it! */ - switch( funcs[ fnum].f_type) { - int sz ; +/* and now evaluate it! */ + switch( FUNID( funcs[ fnum].f_type)) { + int sz, sz1 ; + unicode_t c ; - case UFADD | DYNAMIC: - retstr = i_to_a( atoi( arg1) + atoi( arg2)) ; + case UFADD: + retstr = i_to_a( atoi( argv[ 0]) + atoi( argv[ 1])) ; break ; - case UFSUB | DYNAMIC: - retstr = i_to_a( atoi( arg1) - atoi( arg2)) ; + case UFSUB: + retstr = i_to_a( atoi( argv[ 0]) - atoi( argv[ 1])) ; break ; - case UFTIMES | DYNAMIC: - retstr = i_to_a( atoi( arg1) * atoi( arg2)) ; + case UFTIMES: + retstr = i_to_a( atoi( argv[ 0]) * atoi( argv[ 1])) ; break ; - case UFDIV | DYNAMIC: - sz = atoi( arg2) ; - retstr = (sz == 0) ? errorm : i_to_a( atoi( arg1) / sz) ; + case UFDIV: + sz = atoi( argv[ 1]) ; + retstr = (sz == 0) ? errorm : i_to_a( atoi( argv[ 0]) / sz) ; break ; - case UFMOD | DYNAMIC: - sz = atoi( arg2) ; - retstr = (sz == 0) ? errorm : i_to_a( atoi( arg1) % sz) ; + case UFMOD: + sz = atoi( argv[ 1]) ; + retstr = (sz == 0) ? errorm : i_to_a( atoi( argv[ 0]) % sz) ; break ; - case UFNEG | MONAMIC: - retstr = i_to_a( -atoi( arg1)) ; + case UFNEG: + retstr = i_to_a( -atoi( argv[ 0])) ; break ; - case UFCAT | DYNAMIC: { - int sz1 ; - - sz1 = strlen( arg1) ; - sz = sz1 + strlen( arg2) + 1 ; + case UFCAT: + sz1 = strlen( argv[ 0]) ; + sz = sz1 + strlen( argv[ 1]) + 1 ; if( sz > ressize) { free( result) ; result = malloc( sz) ; ressize = sz ; } - strcpy( result, arg1) ; - strcpy( &result[ sz1], arg2) ; + strcpy( result, argv[ 0]) ; + strcpy( &result[ sz1], argv[ 1]) ; retstr = result ; - } break ; - case UFLEFT | DYNAMIC: { - int sz1, i ; - - sz1 = strlen( arg1) ; + case UFLEFT: + sz1 = strlen( argv[ 0]) ; sz = 0 ; - for( i = atoi( arg2) ; i > 0 ; i -= 1) { + for( int i = atoi( argv[ 1]) ; i > 0 ; i -= 1) { unicode_t c ; - int bytc ; - bytc = utf8_to_unicode( arg1, sz, sz1, &c) ; - if( bytc == 0) + sz += utf8_to_unicode( argv[ 0], sz, sz1, &c) ; + if( sz == sz1) break ; - else - sz += bytc ; } if( sz >= ressize) { @@ -434,41 +409,40 @@ static const char *gtfun( char *fname) { ressize = sz + 1 ; } - mystrscpy( result, arg1, sz + 1) ; + mystrscpy( result, argv[ 0], sz + 1) ; retstr = result ; - } break ; - case UFRIGHT | DYNAMIC: - sz = atoi( arg2) ; + case UFRIGHT: + sz = strlen( argv[ 0]) ; + for( sz1 = atoi( argv[ 1]) ; sz1 > 0 && sz > 0 ; sz1--) + if( --sz > 0) + sz -= utf8_revdelta( (unsigned char *) &( argv[ 0])[ sz], sz) ; + + retstr = &( argv[ 0])[ sz] ; + sz = strlen( retstr) ; if( sz >= ressize) { free( result) ; - result = malloc( sz + 1) ; ressize = sz + 1 ; + result = malloc( ressize) ; } - - retstr = strcpy( result, &arg1[ strlen( arg1) - sz]) ; - break ; - case UFMID | TRINAMIC: { - int sz1, start, i, bytc ; - unicode_t c ; - sz1 = strlen( arg1) ; - start = 0 ; - for( i = atoi( arg2) - 1 ; i > 0 ; i -= 1) { - bytc = utf8_to_unicode( arg1, start, sz1, &c) ; - if( bytc == 0) + retstr = strcpy( result, retstr) ; + break ; + case UFMID: + sz1 = strlen( argv[ 0]) ; + int start = 0 ; + for( i = atoi( argv[ 1]) - 1 ; i > 0 ; i -= 1) { + start += utf8_to_unicode( argv[ 0], start, sz1, &c) ; + if( start == sz1) break ; - else - start += bytc ; } sz = start ; - for( i = atoi( arg3) ; i > 0 ; i -= 1) { - bytc = utf8_to_unicode( arg1, sz, sz1, &c) ; - if( bytc == 0) + if( sz < sz1) + for( i = atoi( argv[ 2]) ; i > 0 ; i -= 1) { + sz += utf8_to_unicode( argv[ 0], sz, sz1, &c) ; + if( sz == sz1) break ; - else - sz += bytc ; } sz -= start ; @@ -478,33 +452,32 @@ static const char *gtfun( char *fname) { ressize = sz + 1 ; } - mystrscpy( result, &arg1[ start], sz + 1) ; + mystrscpy( result, &(argv[ 0][ start]), sz + 1) ; retstr = result ; - } break ; - case UFNOT | MONAMIC: - retstr = ltos( stol( arg1) == FALSE) ; + case UFNOT: + retstr = ltos( stol( argv[ 0]) == FALSE) ; break ; - case UFEQUAL | DYNAMIC: - retstr = ltos( atoi( arg1) == atoi( arg2)) ; + case UFEQUAL: + retstr = ltos( atoi( argv[ 0]) == atoi( argv[ 1])) ; break ; - case UFLESS | DYNAMIC: - retstr = ltos( atoi( arg1) < atoi( arg2)) ; + case UFLESS: + retstr = ltos( atoi( argv[ 0]) < atoi( argv[ 1])) ; break ; - case UFGREATER | DYNAMIC: - retstr = ltos( atoi( arg1) > atoi( arg2)) ; + case UFGREATER: + retstr = ltos( atoi( argv[ 0]) > atoi( argv[ 1])) ; break ; - case UFSEQUAL | DYNAMIC: - retstr = ltos( strcmp( arg1, arg2) == 0) ; + case UFSEQUAL: + retstr = ltos( strcmp( argv[ 0], argv[ 1]) == 0) ; break ; - case UFSLESS | DYNAMIC: - retstr = ltos( strcmp( arg1, arg2) < 0) ; + case UFSLESS: + retstr = ltos( strcmp( argv[ 0], argv[ 1]) < 0) ; break ; - case UFSGREAT | DYNAMIC: - retstr = ltos( strcmp( arg1, arg2) > 0) ; + case UFSGREAT: + retstr = ltos( strcmp( argv[ 0], argv[ 1]) > 0) ; break ; - case UFIND | MONAMIC: - retstr = getval( arg1) ; + case UFIND: + retstr = getval( argv[ 0]) ; sz = strlen( retstr) + 1 ; if( sz > ressize) { free( result) ; @@ -514,123 +487,109 @@ static const char *gtfun( char *fname) { retstr = strcpy( result, retstr) ; break ; - case UFAND | DYNAMIC: - retstr = ltos( stol( arg1) && stol( arg2)) ; + case UFAND: + retstr = ltos( stol( argv[ 0]) && stol( argv[ 1])) ; break ; - case UFOR | DYNAMIC: - retstr = ltos( stol( arg1) || stol( arg2)) ; + case UFOR: + retstr = ltos( stol( argv[ 0]) || stol( argv[ 1])) ; break ; - case UFLENGTH | MONAMIC: - retstr = i_to_a( strlen( arg1)) ; + case UFLENGTH: + retstr = i_to_a( strlen( argv[ 0])) ; break ; - case UFUPPER | MONAMIC: - sz = strlen( arg1) ; + case UFUPPER: + sz = strlen( argv[ 0]) ; if( sz >= ressize) { free( result) ; result = malloc( sz + 1) ; ressize = sz + 1 ; } - retstr = mkupper( result, arg1) ; + retstr = mkupper( result, argv[ 0]) ; break ; - case UFLOWER | MONAMIC: - sz = strlen( arg1) ; + case UFLOWER: + sz = strlen( argv[ 0]) ; if( sz >= ressize) { free( result) ; result = malloc( sz + 1) ; ressize = sz + 1 ; } - strcpy( result, arg1) ; /* result is at least as long as arg1 */ + strcpy( result, argv[ 0]) ; /* result is at least as long as argv[ 0] */ retstr = mklower( result) ; break ; - case UFTRUTH | MONAMIC: - retstr = ltos( atoi( arg1) == 42) ; + case UFTRUTH: + retstr = ltos( atoi( argv[ 0]) == 42) ; break ; - case UFASCII | MONAMIC: { - unicode_t c ; - - utf8_to_unicode( arg1, 0, 4, &c) ; + case UFASCII: + utf8_to_unicode( argv[ 0], 0, 4, &c) ; retstr = i_to_a( c) ; + break ; + case UFCHR: + c = atoi( argv[ 0]) ; + if( c > 0x10FFFF) + retstr = errorm ; + else { + sz = unicode_to_utf8( c, result) ; + result[ sz] = 0 ; + retstr = result ; } break ; - case UFCHR | MONAMIC: { - unicode_t c ; - - c = atoi( arg1) ; - if( c > 0x10FFFF) - retstr = errorm ; - else { - sz = unicode_to_utf8( c, result) ; - result[ sz] = 0 ; - retstr = result ; - } - } - - break ; - case UFGTKEY | NILNAMIC: + case UFGTKEY: result[0] = tgetc(); result[1] = 0; retstr = result ; break ; - case UFRND | MONAMIC: - retstr = i_to_a( ernd( atoi( arg1))) ; + case UFRND: + retstr = i_to_a( ernd( atoi( argv[ 0]))) ; break ; - case UFABS | MONAMIC: - retstr = i_to_a( abs( atoi( arg1))) ; + case UFABS: + retstr = i_to_a( abs( atoi( argv[ 0]))) ; break ; - case UFSINDEX | DYNAMIC: - retstr = i_to_a( sindex( arg1, arg2)) ; + case UFSINDEX: + retstr = i_to_a( sindex( argv[ 0], argv[ 1])) ; break ; - case UFENV | MONAMIC: + case UFENV: #if ENVFUNC - retstr = getenv( arg1) ; + retstr = getenv( argv[ 0]) ; if( retstr == NULL) - retstr = "" ; -#else - retstr = "" ; #endif + retstr = "" ; + break ; - case UFBIND | MONAMIC: - retstr = transbind( arg1) ; + case UFBIND: + retstr = transbind( argv[ 0]) ; break ; - case UFEXIST | MONAMIC: - retstr = ltos( fexist( arg1)) ; + case UFEXIST: + retstr = ltos( fexist( argv[ 0])) ; break ; - case UFFIND | MONAMIC: - retstr = flook( arg1, TRUE) ; + case UFFIND: + retstr = flook( argv[ 0], TRUE) ; if( retstr == NULL) retstr = "" ; break ; - case UFBAND | DYNAMIC: - retstr = i_to_a( atoi( arg1) & atoi( arg2)) ; + case UFBAND: + retstr = i_to_a( atoi( argv[ 0]) & atoi( argv[ 1])) ; break ; - case UFBOR | DYNAMIC: - retstr = i_to_a( atoi( arg1) | atoi( arg2)) ; + case UFBOR: + retstr = i_to_a( atoi( argv[ 0]) | atoi( argv[ 1])) ; break ; - case UFBXOR | DYNAMIC: - retstr = i_to_a( atoi( arg1) ^ atoi( arg2)) ; + case UFBXOR: + retstr = i_to_a( atoi( argv[ 0]) ^ atoi( argv[ 1])) ; break ; - case UFBNOT | MONAMIC: - retstr = i_to_a( ~atoi( arg1)) ; + case UFBNOT: + retstr = i_to_a( ~atoi( argv[ 0])) ; break ; - case UFXLATE | TRINAMIC: - retstr = xlat( arg1, arg2, arg3) ; + case UFXLATE: + retstr = xlat( argv[ 0], argv[ 1], argv[ 2]) ; break ; default: assert( FALSE) ; /* never should get here */ retstr = errorm ; } - if( arg3) - free( arg3) ; - - if( arg2) - free( arg2) ; - - if( arg1) - free( arg1) ; + while( argc > 0) + free( argv[ --argc]) ; return retstr ; } @@ -656,33 +615,55 @@ static char *gtusr( char *vname) { return errorm; } -/* - * gtenv() + +/* getctext: grab and return a string with the text of the current line */ +static const char *getctext( void) { + static int rsize = 0 ; + static char *rline = NULL ; /* line to return */ + +/* find the contents of the current line and its length */ + line_p lp = curwp->w_dotp ; /* line to copy */ + int size = lp->l_used ; /* length of line to return */ + if( size >= rsize) { + /* extend storage */ + int newsize = size + 1 ; + char *newstr = realloc( rline, newsize) ; + if( newstr == NULL) + return "" ; + + rline = newstr ; + rsize = newsize ; + } + + /* copy it across */ + memcpy( rline, lp->l_text, size) ; + rline[ size] = 0 ; + return rline ; +} + + +/* gtenv() * * char *vname; name of environment variable to retrieve */ -static char *gtenv( char *vname) { +static const char *gtenv( char *vname) { unsigned vnum ; /* ordinal number of var referenced */ /* scan the list, looking for the referenced name */ - for (vnum = 0; vnum < ARRAY_SIZE(envars); vnum++) - if (strcmp(vname, envars[vnum]) == 0) - break; + for( vnum = 0 ; vnum < ARRAY_SIZE( envars) ; vnum++) + if( strcmp( vname, envars[ vnum]) == 0) + break ; /* return errorm on a bad reference */ - if (vnum == ARRAY_SIZE(envars)) + if( vnum == ARRAY_SIZE( envars)) { #if ENVFUNC - { char *ename = getenv(vname); - if (ename != NULL) - return ename; - else - return errorm; - } -#else - return errorm; + if( ename != NULL) + return ename ; #endif + return errorm ; + } /* otherwise, fetch the appropriate value */ switch (vnum) { @@ -778,6 +759,8 @@ static char *gtenv( char *vname) { return i_to_a( tabwidth) ; case EVHARDTAB: return ltos( hardtab) ; + case EVVIEWTAB: + return ltos( viewtab) ; case EVOVERLAP: return i_to_a(overlap); case EVSCROLLCOUNT: @@ -803,7 +786,7 @@ static char *gtenv( char *vname) { */ BINDABLE( setvar) { int status; /* status return */ - struct variable_description vd; /* variable num/type */ + variable_description vd ; /* variable num/type */ char var[NVSIZE + 2]; /* name of variable to fetch %1234567890\0 */ char *value ; /* value to set variable to */ @@ -891,7 +874,7 @@ int mdbugout( char *fmt, ...) { * @vd: structure to hold type and pointer. * @size: size of variable array. */ -static void findvar(char *var, struct variable_description *vd, int size) +static void findvar(char *var, variable_description *vd, int size) { unsigned vnum = 0 ; /* subscript in variable arrays */ int vtype; /* type to return */ @@ -947,7 +930,7 @@ fvar: * @var: variable to set. * @value: value to set to. */ -static int svar(struct variable_description *var, char *value) +static int svar( variable_description *var, char *value) { int vnum; /* ordinal number of var refrenced */ int vtype; /* type of variable to set */ @@ -1100,6 +1083,9 @@ static int svar(struct variable_description *var, char *value) case EVHARDTAB: hardtab = stol( value) ; break ; + case EVVIEWTAB: + viewtab = stol( value) ; + break ; case EVOVERLAP: overlap = atoi(value); break; @@ -1125,7 +1111,7 @@ static int svar(struct variable_description *var, char *value) * * int i; integer to translate to a string */ -static char *i_to_a( int i) { +static const char *i_to_a( int i) { unsigned u ; int sign ; /* sign of resulting number */ /* returns result string: sign digits null */ @@ -1151,116 +1137,103 @@ static char *i_to_a( int i) { return sp ; } -/* - * find the type of a passed token + +/* find the type of a token based on first character * - * char *token; token to analyze + * char c ; first character of analyzed token */ -static int gettyp( char *token) { - char c; /* first char in token */ - - /* grab the first char (this is all we need) */ - c = *token; - - switch (c) { +static int gettyp( char c) { + switch( c) { + case '*': + case ':': + return TKLBL ; case 0: /* no blanks!!! */ return TKNUL ; case '"': - return TKSTR; - + return TKSTR ; case '!': - return TKDIR; + return TKDIR ; case '@': - return TKARG; + return TKARG ; case '=': - return TKBUF; + return TKBUF ; case '$': - return TKENV; + return TKENV ; case '%': - return TKVAR; + return TKVAR ; case '&': - return TKFUN; - case '*': - return TKLBL; + return TKFUN ; default: /* a numeric literal? */ if( (c >= '0' && c <= '9') || c == '-') - return TKLIT; + return TKLIT ; else - return TKCMD; + return TKCMD ; } } int is_it_cmd( char *token) { - return TKCMD == gettyp( token) ; + return TKCMD == gettyp( *token) ; } -/* - * find the value of a token + +/* find the value of a token * * char *token; token to evaluate */ -const char *getval(char *token) -{ - int status; /* error return */ - struct buffer *bp; /* temp buffer pointer */ - unsigned blen ; /* length of buffer argument */ - int distmp; /* temporary discmd flag */ - static char buf[NSTRING]; /* string buffer for some returns */ - - switch (gettyp(token)) { - case TKNUL: - return ""; +const char *getval( char *token) { + static char buf[ NSTRING] ; /* string buffer for some returns */ + switch( gettyp( *token)) { case TKARG: /* interactive argument */ - strcpy(token, getval(&token[1])); - distmp = discmd; /* echo it always! */ - discmd = TRUE; - status = getstring( token, buf, NSTRING, nlc) ; - discmd = distmp; + strcpy( token, getval( &token[ 1])) ; + int distmp = discmd ; /* echo it always! */ + discmd = TRUE ; + int status = getstring( token, buf, NSTRING, nlc) ; + discmd = distmp ; if (status == ABORT) - return errorm; - return buf; + return errorm ; + + return buf ; case TKBUF: /* buffer contents fetch */ - - /* grab the right buffer */ - strcpy(token, getval(&token[1])); - bp = bfind(token, FALSE, 0); + /* grab the right buffer */ + strcpy( token, getval( &token[ 1])) ; + buffer_p bp = bfind( token, FALSE, 0) ; if (bp == NULL) - return errorm; + return errorm ; - /* if the buffer is displayed, get the window - vars instead of the buffer vars */ + /* if the buffer is displayed, + get the window vars instead of the buffer vars */ if (bp->b_nwnd > 0) { curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; } - /* make sure we are not at the end */ + /* make sure we are not at the end */ if (bp->b_linep == bp->b_dotp) return errorm; - /* grab the line as an argument */ - blen = bp->b_dotp->l_used - bp->b_doto; + /* grab the line as an argument */ + unsigned blen = bp->b_dotp->l_used - bp->b_doto; if( blen >= sizeof buf) blen = sizeof buf - 1 ; mystrscpy( buf, bp->b_dotp->l_text + bp->b_doto, blen + 1) ; - /* and step the buffer's line ptr ahead a line */ + /* and step the buffer's line ptr ahead a line */ bp->b_dotp = bp->b_dotp->l_fp; bp->b_doto = 0; - /* if displayed buffer, reset window ptr vars */ + /* if displayed buffer, reset window ptr vars */ if (bp->b_nwnd > 0) { curwp->w_dotp = curbp->b_dotp; curwp->w_doto = 0; curwp->w_flag |= WFMOVE; } - /* and return the spoils */ + /* and return the spoils */ return buf; case TKVAR: @@ -1269,18 +1242,19 @@ const char *getval(char *token) return gtenv(token + 1); case TKFUN: return gtfun(token + 1); - case TKDIR: - return errorm; - case TKLBL: - return errorm; case TKLIT: return token; case TKSTR: return token + 1; case TKCMD: return token; + case TKDIR: + case TKLBL: + case TKNUL: + return "" ; } - return errorm; + + return errorm ; } /* @@ -1368,30 +1342,26 @@ static int ernd( int i) { return (i <= 0) ? s : s % i + 1 ; } -/* - * find pattern within source + +/* find pattern within source * * char *source; source string to search * char *pattern; string to look for */ static int sindex( char *source, char *pattern) { - char *sp; /* ptr to current position to scan */ - - /* scanning through the source string */ - sp = source; +/* scanning through the source string */ + char *sp = source ; /* ptr to current position to scan */ int idx = 1 ; int pos = 0 ; int len = strlen( source) ; - while (*sp) { - char *csp; /* ptr to source string during comparison */ - char *cp; /* ptr to place to check for equality */ + while( *sp) { char c ; unicode_t uc ; /* scan through the pattern */ - cp = pattern; - csp = sp; + char *cp = pattern ; /* ptr to place to check for equality */ + char *csp = sp ; /* ptr to source string during comparison */ while( (c = *cp++) && eq( c, *csp)) csp++ ; @@ -1406,7 +1376,7 @@ static int sindex( char *source, char *pattern) { } /* no match at all.. */ - return 0; + return 0 ; } /* diff --git a/eval.h b/eval.h index af9e838..41d71d6 100644 --- a/eval.h +++ b/eval.h @@ -12,7 +12,7 @@ extern int macbug ; /* macro debuging flag */ extern int cmdstatus ; /* last command status */ extern int rval ; /* return value of a subprocess */ -extern long envram ; /* # of bytes current in use by malloc */ +extern unsigned envram ; /* # of bytes current in use by malloc */ int readfirst_f( void) ; int is_it_cmd( char *token) ; diff --git a/exec.c b/exec.c index e85134d..b6577d4 100644 --- a/exec.c +++ b/exec.c @@ -8,16 +8,19 @@ modified by Petri Kutvonen */ +#include #include #include #include "buffer.h" #include "bind.h" +#include "defines.h" /* malloc/allocate, free/release */ #include "eval.h" #include "file.h" #include "flook.h" #include "input.h" #include "line.h" +#include "list.h" #include "mlout.h" #include "random.h" #include "util.h" @@ -26,19 +29,34 @@ static char *execstr = NULL ; /* pointer to string to execute */ boolean clexec = FALSE ; /* command line execution flag */ -/* Directive definitions */ -#define DIF 0 +/* Directive definitions */ +#define DBREAK 0 #define DELSE 1 #define DENDIF 2 -#define DGOTO 3 -#define DRETURN 4 -#define DENDM 5 -#define DWHILE 6 -#define DENDWHILE 7 -#define DBREAK 8 -#define DFORCE 9 +#define DENDM 3 +#define DENDWHILE 4 +#define DFORCE 5 +#define DGOTO 6 +#define DGOSUB 7 +#define DIF 8 +#define DRETURN 9 +#define DWHILE 10 +/* directive name table: holds the names of all the directives.... */ +static const char *dname[] = { + "break", "else", "endif", "endm", "endwhile", + "force", "goto", "gosub", "if", "return", + "while" +} ; + +#define NUMDIRS ARRAY_SIZE( dname) + + +typedef struct caller { + struct caller *next ; + line_p caller ; +} *caller_p ; /* The !WHILE directive in the execution language needs to * stack references to pending whiles. These are stored linked @@ -46,28 +64,18 @@ boolean clexec = FALSE ; /* command line execution flag */ * the following structure. */ typedef struct while_block { + struct while_block *w_next ; /* next while */ line_p w_begin ; /* ptr to !while statement */ line_p w_end ; /* ptr to the !endwhile statement */ int w_type ; /* block type */ - struct while_block *w_next ; /* next while */ } *while_p ; #define BTWHILE 1 #define BTBREAK 2 -/* directive name table: holds the names of all the directives.... */ - -static const char *dname[] = { - "if", "else", "endif", "goto", "return", - "endm", "while", "endwhile", "break", "force" -} ; - -#define NUMDIRS ARRAY_SIZE( dname) - static char golabel[ NSTRING] = "" ; /* current line to go to */ -static int execlevel = 0 ; /* execution IF level */ static buffer_p bstore = NULL ; /* buffer to store macro text to */ -static int mstore = FALSE ; /* storing text to macro flag */ +static int storing_f = FALSE ; /* storing text to macro flag */ static int dobuf( buffer_p bp) ; static int macarg( char *tok, int toksz) ; @@ -93,53 +101,23 @@ BINDABLE( namedcmd) { return kfunc( f, n) ; } -static int docmd( char *cline) ; - -/* execcmd: - * Execute a command line command to be typed in - * by the user - * - * int f, n; default Flag and Numeric argument - */ -BINDABLE( execcmd) { - char *cmdstr ; /* string holding command to execute */ - -/* get the line wanted */ - int status = newmlarg( &cmdstr, "execute-command-line: ", 0) ; - if( status != TRUE) - return status ; - - execlevel = 0 ; - while( status == TRUE && n-- > 0) - status = docmd( cmdstr) ; - - free( cmdstr) ; - return status ; -} - /* docmd: - * take a passed string as a command line and translate - * it to be executed as a command. This function will be - * used by execute-command-line and by all source and - * startup files. Lastflag/thisflag is also updated. - * - * format of the command line is: + take a passed string as a command line and translate it to be executed + as a command. This function will be used by execute-command-line and by + all source and startup files. Lastflag/thisflag is also updated. + + * format of the command line is: * * {# arg} {} * * char *cline; command line to execute */ static int docmd( char *cline) { - boolean oldcle ; /* old contents of clexec flag */ - char *oldestr ; /* original exec string */ - char tkn[NSTRING] ; /* next token off of command line */ + char tkn[ NSTRING] ; /* next token off of command line */ + int status ; - /* if we are scanning and not executing..go back here */ - if (execlevel) - return TRUE ; - - oldestr = execstr ; /* save last ptr to string to execute */ - execstr = cline ; /* and set this one as current */ + char *oldestr = execstr ; /* save last ptr to string to execute */ + execstr = cline ; /* and set this one as current */ /* first set up the default command values */ int f = FALSE ; @@ -147,27 +125,22 @@ static int docmd( char *cline) { lastflag = thisflag ; thisflag = 0 ; - int status = macarg( tkn, sizeof tkn) ; - if( status != TRUE) { /* and grab the first token */ - execstr = oldestr; - return status; - } + for( ;;) { + /* evaluate next token */ + status = macarg( tkn, sizeof tkn) ; + if( status != TRUE || !*tkn) { + execstr = oldestr ; + return status ; + } - /* process leadin argument */ - if( !is_it_cmd( tkn)) { - f = TRUE; -/* macarg already includes a getval, skip for now - mystrscpy( tkn, getval( tkn), sizeof tkn) ; -*/ - n = atoi(tkn); + /* proceed if it is a command */ + if( is_it_cmd( tkn)) + break ; - /* and now get the command to execute */ - status = macarg( tkn, sizeof tkn) ; - if( status != TRUE) { - execstr = oldestr; - return status; - } - } + /* otherwise set as argument of coming command */ + f = TRUE ; + n = atoi( tkn) ; + } /* and match the token to see if it exists */ nbind_p nbp = fncmatch( tkn) ; @@ -181,19 +154,39 @@ static int docmd( char *cline) { status = rdonly() ; else { /* save the arguments and go execute the command */ - oldcle = clexec; /* save old clexec flag */ - clexec = TRUE; /* in cline execution */ - status = fnc( f, n) ; /* call the function */ - clexec = oldcle; /* restore clexec flag */ - execstr = oldestr; + boolean oldcle = clexec ; /* save old clexec flag */ + clexec = TRUE ; /* in cline execution */ + status = fnc( f, n) ; /* call the function */ + clexec = oldcle ; /* restore clexec flag */ + execstr = oldestr ; } - cmdstatus = status; /* save the status */ - return status; + cmdstatus = status ; /* save the status */ + return status ; } -/* - * new token: + +/* execcmd: + * Execute a command line command to be typed in by the user + * + * int f, n; default Flag and Numeric argument + */ +BINDABLE( execcmd) { + char *cmdstr ; /* string holding command to execute */ + +/* get the line wanted */ + int status = newmlarg( &cmdstr, "execute-command-line: ", 0) ; + if( status != TRUE) + return status ; + + while( status == TRUE && n-- > 0) + status = docmd( cmdstr) ; + + free( cmdstr) ; + return status ; +} + +/* new token: * chop a token off a string * return a pointer past the token * @@ -210,52 +203,51 @@ static char *newtoken( char *src, char **tokref) { ++src ; /* scan through the source string */ - boolean quotef = FALSE ; /* is the current string quoted? */ - while( *src) { - char c ; /* temporary character */ + boolean quote_f = FALSE ; /* is the current string quoted? */ + char c = *src ; + for( ; c ; c = *++src) { + /* process special characters */ + if( c == '~') { + c = *++src ; + if( c == 0) + break ; - /* process special characters */ - if( *src == '~') { - ++src; - if (*src == 0) - break; - switch (*src++) { + switch( c) { case 'r': - c = 13; - break; + c = 13 ; + break ; case 'n': - c = 10; - break; + c = 10 ; + break ; case 't': - c = 9; - break; + c = 9 ; + break ; case 'b': - c = 8; - break; + c = 8 ; + break ; case 'f': - c = 12; - break; - default: - c = *(src - 1); + c = 12 ; + break ; } } else { - /* check for the end of the token */ - if (quotef) { - if (*src == '"') - break; - } else { - if (*src == ' ' || *src == '\t') - break; - } + /* check for the end of the token: EOS, space or comment */ + if( quote_f) { + if( c == '"') + break ; + } else if( c == ' ' || c == '\t') + break ; + else if( c == '#' || c == ';') { + /* comments act like EOS */ + c = 0 ; + break ; + } - /* set quote mode if quote found */ - if (*src == '"') - quotef = TRUE; - - /* record the character */ - c = *src++; + /* set quote mode if quote found */ + if( c == '"') + quote_f = TRUE ; } + /* record the character */ if( idx < size - 1) tok[ idx++] = c ; else if( size > 1) { @@ -263,7 +255,7 @@ static char *newtoken( char *src, char **tokref) { tmptok = malloc( size + 32) ; if( tmptok == NULL) - size = 0 ; + size = 0 ; /* can't store more */ else { memcpy( tmptok, tok, idx) ; free( tok) ; @@ -274,15 +266,11 @@ static char *newtoken( char *src, char **tokref) { } } - /* terminate the token and exit */ - if (*src) - ++src; - if( tok != NULL) tok[ idx] = 0 ; *tokref = tok ; - return src; + return src + (c != 0) ; } static char *token( char *srcstr, char *tok, int maxtoksize) { @@ -359,10 +347,9 @@ static int macarg( char *tok, int toksz) { return status ; } -/* - * storemac: - * Set up a macro buffer and flag to store all - * executed command lines there + +/* storemac: + * Set up a macro buffer and start recording all command lines until !endm * * int f; default flag * int n; macro number to use @@ -370,7 +357,24 @@ static int macarg( char *tok, int toksz) { static char macbufname[] = "*Macro xx*" ; #define MACDIGITPOS 7 -BINDABLE( storemac) { +static boolean setstore( char *bufname) { +/* set up the new macro buffer */ + bstore = bfind( bufname, TRUE, BFINVS) ; + if( bstore == NULL) { + storing_f = FALSE ; /* should be already the case as we are executing */ + return mloutfail( "Can not create macro") ; + } + +/* and make sure it is empty */ + bclear( bstore) ; + +/* start recording */ + storing_f = TRUE ; + return TRUE ; +} + + +BBINDABLE( storemac) { /* must have a numeric argument to this function */ if( f == FALSE) return mloutfail( "No macro number specified"); @@ -383,22 +387,11 @@ BINDABLE( storemac) { macbufname[ MACDIGITPOS] = '0' + (n / 10) ; macbufname[ MACDIGITPOS + 1] = '0' + (n % 10) ; -/* set up the new macro buffer */ - buffer_p bp = bfind( macbufname, TRUE, BFINVS) ; - if( bp == NULL) - return mloutfail( "Can not create macro") ; - -/* and make sure it is empty */ - bclear( bp) ; - -/* and set the macro store pointers to it */ - mstore = TRUE ; - bstore = bp ; - return TRUE ; + return setstore( macbufname) ; } -/* -** exec -- execute a buffer + +/* exec -- execute a buffer ** common to execute buffer, procedure and macro */ static int exec( int n, char *bufname, char *errstr) { @@ -417,10 +410,9 @@ static int exec( int n, char *bufname, char *errstr) { return status ; } -/* - * storeproc: - * Set up a procedure buffer and flag to store all - * executed command lines there + +/* storeproc: + * Set up a procedure buffer and start recording all command lines until !endm * * int f; default flag * int n; macro number to use @@ -429,7 +421,7 @@ BINDABLE( storeproc) { bname_t bname ; /* name of buffer to use */ char *name ; - /* a numeric argument means its a numbered macro */ + /* a numeric argument means it is a numbered macro */ if( f == TRUE) return storemac( f, n) ; @@ -444,22 +436,11 @@ BINDABLE( storeproc) { strcat( bname, "*") ; free( name) ; - /* set up the new macro buffer */ - buffer_p bp = bfind( bname, TRUE, BFINVS) ; - if( bp == NULL) - return mloutfail( "Can not create macro") ; - - /* and make sure it is empty */ - bclear( bp) ; - - /* and set the macro store pointers to it */ - mstore = TRUE ; - bstore = bp ; - return TRUE ; + return setstore( bname) ; } -/* - * execproc: + +/* execproc: * Execute a procedure * * int f, n; default flag and numeric arg @@ -492,7 +473,7 @@ BINDABLE( execbuf) { char *bufn ; /* name of buffer to execute */ /* find out what buffer the user wants to execute */ - int status = newmlarg( &bufn, "Execute buffer: ", sizeof( bname_t)) ; + int status = newmlarg( &bufn, "execute-buffer: ", sizeof( bname_t)) ; if( status != TRUE) return status ; @@ -502,22 +483,26 @@ BINDABLE( execbuf) { } -/* free a list of while block pointers - * - * while_p wp; head of structure to free - */ -static void freewhile( while_p wp) { - while( wp != NULL) { - while_p next = wp->w_next ; - free( wp) ; - wp = next ; - } +static boolean storeline( char *eline, int linlen) { +/* allocate the space for the line */ + line_p mp = lalloc( linlen) ; + if( mp == NULL) + return mloutfail( "Out of memory while storing macro") ; + +/* copy the text into the new line */ + memcpy( mp->l_text, eline, linlen) ; /* lalloc has set lp->l_used */ + +/* attach the line to the end of the buffer */ + bstore->b_linep->l_bp->l_fp = mp ; + mp->l_bp = bstore->b_linep->l_bp ; + bstore->b_linep->l_bp = mp ; + mp->l_fp = bstore->b_linep ; + return TRUE ; } /* dobuf: - * execute the contents of the buffer pointed to - * by the passed BP + * execute the contents of the buffer pointed to by the passed BP * * Directives start with a "!" and include: * @@ -531,135 +516,207 @@ static void freewhile( while_p wp) { * !while (cond) Execute a loop if the condition is true * !endwhile * - * Line Labels begin with a "*" as the first nonblank char, like: + * Line Labels begin with a "*" or ':' as the first nonblank char, like: * - * *LBL01 + * *LBL01 or :LBL01 * * buffer_p bp; buffer to execute */ static int dobuf( buffer_p bp) { - int linlen ; /* length of line to execute */ - int i ; /* index */ while_p whtemp ; /* temporary ptr to a struct while_block */ char *eline ; /* text of line to execute */ char tkn[ NSTRING] ; /* buffer to evaluate an expression in */ + int w_type ; /* either while or break */ /* clear IF level flags/while ptr */ - execlevel = 0 ; while_p whlist = NULL ; /* ptr to !WHILE list */ while_p scanner = NULL ; /* ptr during scan */ -/* scan the buffer to execute, building WHILE header blocks */ - line_p hlp = bp->b_linep ; /* pointer to line header */ +/* range of lines with labels, initially no lines in range */ + line_p firstlbl = NULL ; + line_p eolbl = firstlbl ; + +/* parse the buffer to execute, building WHILE header blocks */ + storing_f = FALSE ; + const line_p hlp = bp->b_linep ; /* pointer to line header */ for( line_p lp = hlp->l_fp ; lp != hlp ; lp = lp->l_fp) { /* scan the current line */ eline = lp->l_text ; - i = lp->l_used ; + char const *eol = &eline[ lp->l_used] ; + for( ; eline < eol ; eline++) + if( *eline != ' ' && *eline != '\t') + break ; - /* trim leading whitespace */ - while (i-- > 0 && (*eline == ' ' || *eline == '\t')) - ++eline; + /* delete blank and comment lines */ + if( eline == eol || *eline == '#' || *eline == ';') { + lp = lp->l_bp ; + lfree( lp->l_fp) ; + continue ; + } - /* if theres nothing here, don't bother */ - if( i <= 0) - continue ; + /* remove leading spaces */ + if( eline != lp->l_text) { + int size = lp->l_used = eol - eline ; + if( size) + memcpy( lp->l_text, eline, size) ; - /* if it is a while directive, make a block... */ - if( eline[0] == '!' - && eline[1] == 'w' - && eline[2] == 'h') { - whtemp = malloc( sizeof *whtemp) ; - if( whtemp == NULL) { - noram: + eline = lp->l_text ; + eol = &lp->l_text[ size] ; + } + + /* handle storing */ + if( storing_f) { + if( !strncmp( eline, "!endm", 5)) { + bstore = NULL ; + storing_f = FALSE ; + } else if( bstore && !storeline( lp->l_text, lp->l_used)) + goto failexit ; + + /* remove line */ + lp = lp->l_bp ; + lfree( lp->l_fp) ; + continue ; + } + + /* process labels, update the range of lines containing labels */ + if( *eline == ':' || *eline == '*') { + if( firstlbl == NULL) + firstlbl = lp ; + + eolbl = lp->l_fp ; + continue ; + } + + /* process directives, skip others */ + if( *eline != '!') + continue ; + + if( !strncmp( eline, "!store", 6)) { + /* turn line into a string */ + int size = lp->l_used - 6 ; + if( size) + memcpy( lp->l_text, &eline[ 6], size) ; + + eline = lp->l_text ; + eline[ size] = 0 ; + lp->l_used = size ; + + /* get procedure or macro name */ + token( eline, &tkn[ 1], sizeof tkn - 1) ; + char c = tkn[ 1] ; + if( !c) { + /* no name */ + storing_f = TRUE ; /* just throw away the lines (no bstore) */ + } else if( c >= '1' && c <= '9') { /* number >= 1 */ + /* macro number */ + if( !storemac( TRUE, atoi( &tkn[ 1]))) + goto failexit ; + } else { + /* whatever */ + *tkn = '*' ; + strcat( tkn, "*") ; + if( !setstore( tkn)) + goto failexit ; + } + + /* remove line */ + lp = lp->l_bp ; + lfree( lp->l_fp) ; + continue ; + } else if( !strncmp( eline, "!while", 6)) { + /* if it is a while directive, make a block... */ + w_type = BTWHILE ; + scan: + whtemp = malloc( sizeof *whtemp) ; + if( whtemp == NULL) { mloutstr( "%%Out of memory during while scan") ; - failexit: - freewhile( scanner) ; - freewhile( whlist) ; - return FALSE ; - } + goto failexit ; + } - whtemp->w_begin = lp ; - whtemp->w_type = BTWHILE ; - whtemp->w_next = scanner ; - scanner = whtemp ; - } + whtemp->w_begin = lp ; + whtemp->w_type = w_type ; + whtemp->w_next = scanner ; + scanner = whtemp ; + } else if( !strncmp( eline, "!break", 6)) { + /* if is a BREAK directive, make a block... */ + if( scanner == NULL) { + mloutstr( "%%!BREAK outside of any !WHILE loop") ; + goto failexit ; + } - /* if is a BREAK directive, make a block... */ - if( eline[0] == '!' - && eline[1] == 'b' - && eline[2] == 'r') { - if (scanner == NULL) { - mloutstr( "%%!BREAK outside of any !WHILE loop") ; - goto failexit ; - } - - whtemp = malloc( sizeof *whtemp) ; - if( whtemp == NULL) - goto noram ; - - whtemp->w_begin = lp; - whtemp->w_type = BTBREAK; - whtemp->w_next = scanner; - scanner = whtemp; - } - - /* if it is an endwhile directive, record the spot... */ - if( eline[0] == '!' - && strncmp( &eline[1], "endw", 4) == 0) { - if (scanner == NULL) { - mloutfmt( "%%!ENDWHILE with no preceding !WHILE in '%s'", + w_type = BTBREAK ; + goto scan ; + } else if( !strncmp( eline, "!endwhile", 9)) { + /* if it is an endwhile directive, record the spot... */ + if( scanner == NULL) { + mloutfmt( "%%!ENDWHILE with no preceding !WHILE in '%s'", bp->b_bname) ; - goto failexit ; - } - - /* move top records from the scanner list to the - whlist until we have moved all BREAK records - and one WHILE record */ - do { - scanner->w_end = lp ; - whtemp = whlist ; - whlist = scanner ; - scanner = scanner->w_next ; - whlist->w_next = whtemp ; + goto failexit ; + } + + /* move top records from the scanner list to the whlist until we + have moved all BREAK records and one WHILE record */ + do { + scanner->w_end = lp ; + whtemp = whlist ; + whlist = scanner ; + scanner = scanner->w_next ; + whlist->w_next = whtemp ; } while( whlist->w_type == BTBREAK) ; } } - /* while and endwhile should match! */ +/* check consistency after parsing */ + if( storing_f) { + /* missing !endm */ + mloutstr( "!store without !endm") ; + goto failexit ; + } + if( scanner != NULL) { + /* while and endwhile should match! */ mloutfmt( "%%!WHILE with no matching !ENDWHILE in '%s'", bp->b_bname) ; - goto failexit ; + failexit: + freelist( (list_p) scanner) ; + freelist( (list_p) whlist) ; + return FALSE ; } +/* execute the parsed buffer */ /* let the first command inherit the flags from the last one.. */ thisflag = lastflag; /* starting at the beginning of the buffer */ - hlp = bp->b_linep ; char *einit = NULL ; /* initial value of eline */ + int esize = 0 ; /* size available for storage in einit */ int status = TRUE ; /* status of command execution */ boolean done = FALSE ; - for( line_p lp = hlp->l_fp ; !done && (lp != hlp) ; lp = lp->l_fp) { - if( einit) - free( einit) ; + int execlevel = 0 ; /* execution IF level */ + caller_p returnto = NULL ; + line_p lp = hlp->l_fp ; + for( ; lp != hlp ; lp = lp->l_fp) { + /* turns macro line into a string pointed by eline */ + int length = lp->l_used ; + if( length < lp->l_size) { + /* there is space for EOS, let's use the line */ + eline = lp->l_text ; + } else { + /* make a copy using (pre-)allocated storage */ + if( esize <= length) { + esize = length + 1 ; + char *newbuf = realloc( einit, esize) ; + if( newbuf == NULL) { + status = mloutfail( "%%Out of Memory during macro execution") ; + break ; + } else + einit = newbuf ; + } - /* allocate eline and copy macro line to it */ - linlen = lp->l_used ; - einit = eline = malloc( linlen + 1) ; - if( eline == NULL) { - status = mloutfail( "%%Out of Memory during macro execution") ; - break ; - } + eline = einit ; + memcpy( eline, lp->l_text, length) ; + } - mystrscpy( eline, lp->l_text, linlen + 1) ; - - /* trim leading whitespace */ - while( *eline == ' ' || *eline == '\t') - ++eline ; - - /* dump comments and blank lines */ - if( *eline == ';' || *eline == '#' || *eline == 0) - continue ; + eline[ length] = 0 ; #if DEBUGM /* if $debug == TRUE, every line to execute @@ -667,10 +724,8 @@ static int dobuf( buffer_p bp) { ^G will abort the command */ if( macbug) { - int c ; - - /* debug macro name, if levels and lastly the line */ - c = mdbugout( "<<<%s:%d:%s>>>", bp->b_bname, execlevel, eline) ; + /* debug macro name, if levels and lastly the line */ + int c = mdbugout( "<<<%s:%d:%s>>>", bp->b_bname, execlevel, eline) ; if( c == abortc) { status = FALSE ; break ; @@ -680,208 +735,205 @@ static int dobuf( buffer_p bp) { } #endif + /* if macro store is on, just salt this away */ + if( storing_f) { + if( !strncmp( eline, "!endm", 5)) { + storing_f = FALSE ; + bstore = NULL ; + lp = lp->l_bp ; + lfree( lp->l_fp) ; + } else { + status = storeline( eline, strlen( eline)) ; + if( status != TRUE) + break ; + } + + lp = lp->l_bp ; + lfree( lp->l_fp) ; + continue ; + } + + /* skip labels */ + if( *eline == '*' || *eline == ':') + continue ; + /* Parse directives here.... */ - unsigned dirnum = NUMDIRS ; /* directive index */ if( *eline == '!') { /* Find out which directive this is */ ++eline ; - for( dirnum = 0 ; dirnum < NUMDIRS ; dirnum++) - if( !strncmp( eline, dname[ dirnum], strlen( dname[ dirnum]))) - break ; + int dirnum = NUMDIRS ; + while( --dirnum >= 0) { + length = strlen( dname[ dirnum]) ; + if( !strncmp( eline, dname[ dirnum], length )) { + eline += length ; + /* either EOS, comment, space separator or FAIL */ + if( !*eline || *eline == ';' || *eline == '#') + ; + else if( *eline == ' ' || *eline == '\t') { + eline += 1 ; + } else + dirnum = -1 ; - /* and bitch if it's illegal */ - if( dirnum == NUMDIRS) { - status = mloutfail( "%%Unknown Directive") ; - break ; - } + execstr = eline ; /* set source of token() and macarg() */ + break ; + } + } - /* service only the !ENDM macro here */ - if( dirnum == DENDM) { - mstore = FALSE ; - bstore = NULL ; - continue ; - } - - /* restore the original eline.... */ - --eline ; - } - - /* if macro store is on, just salt this away */ - if( mstore) { - /* allocate the space for the line */ - linlen = strlen( eline) ; - line_p mp = lalloc( linlen) ; - if( mp == NULL) { - status = mloutfail( "Out of memory while storing macro") ; - break ; - } - - /* copy the text into the new line */ - for( i = 0 ; i < linlen ; ++i) - lputc( mp, i, eline[ i]) ; - - /* attach the line to the end of the buffer */ - bstore->b_linep->l_bp->l_fp = mp ; - mp->l_bp = bstore->b_linep->l_bp ; - bstore->b_linep->l_bp = mp ; - mp->l_fp = bstore->b_linep ; - continue ; - } - - int force = FALSE ; /* force TRUE result? */ - - /* dump comments */ - if( *eline == '*') - continue ; - - /* now, execute directives */ - if( dirnum != NUMDIRS) { - /* skip past the directive */ - while( *eline && *eline != ' ' && *eline != '\t') - ++eline ; - - execstr = eline; + /* now, execute directives */ switch( dirnum) { + case DENDM: + if( execlevel == 0) + status = mloutfail( "!endm out of context") ; + + break ; case DIF: /* IF directive */ - /* grab the value of the logical exp */ if( execlevel == 0) { - if( macarg( tkn, sizeof tkn) != TRUE) - done = TRUE ; - else if( stol( tkn) == FALSE) - ++execlevel ; + /* grab the value of the logical exp */ + status = macarg( tkn, sizeof tkn) ; + if( status == TRUE && stol( tkn) == FALSE) + execlevel = 1 ; /* skip to else or endif */ } else ++execlevel ; - continue ; + break ; + case DELSE: /* ELSE directive */ + if( execlevel == 1) + execlevel = 0 ; /* execute the else part */ + else if( execlevel == 0) + execlevel = 1 ; /* skip to endif */ + /* else keep skipping */ + break ; + case DENDIF: /* ENDIF directive */ + if( execlevel) + --execlevel ; + + break ; case DWHILE: /* WHILE directive */ - /* grab the value of the logical exp */ if( execlevel == 0) { - if( macarg( tkn, sizeof tkn) != TRUE) { - done = TRUE ; - continue ; - } else if( stol( tkn) == TRUE) - continue ; + /* grab the value of the logical exp */ + status = macarg( tkn, sizeof tkn) ; + if( status != TRUE || stol( tkn) == TRUE) + break ; } - /* drop down and act just like !BREAK */ /* fallthrough */ case DBREAK: /* BREAK directive */ - if( dirnum == DBREAK && execlevel) - continue ; + /* jump down to the endwhile */ + /* find the right while loop */ + for( whtemp = whlist ; whtemp ; whtemp = whtemp->w_next) + if( whtemp->w_begin == lp) { + /* reset the line pointer back.. */ + lp = whtemp->w_end ; + break ; + } - /* jump down to the endwhile */ + if( whtemp == NULL) + status = mloutfail( "%%Internal While loop error") ; + + break ; + case DENDWHILE: /* ENDWHILE directive */ + assert( execlevel == 0) ; /* find the right while loop */ for( whtemp = whlist ; whtemp ; whtemp = whtemp->w_next) - if( whtemp->w_begin == lp) + if( whtemp->w_type == BTWHILE && whtemp->w_end == lp) { + /* reset the line pointer back.. */ + lp = whtemp->w_begin->l_bp ; break ; + } - if( whtemp == NULL) { + if( whtemp == NULL) status = mloutfail( "%%Internal While loop error") ; - done = TRUE ; - } else - /* reset the line pointer back.. */ - lp = whtemp->w_end ; - - continue ; - - case DELSE: /* ELSE directive */ - if( execlevel == 1) - --execlevel ; - else if( execlevel == 0) - ++execlevel ; - - continue ; - - case DENDIF: /* ENDIF directive */ - if (execlevel) - --execlevel; - - continue ; + break ; + case DGOSUB: /* GOSUB directive */ case DGOTO: /* GOTO directive */ /* .....only if we are currently executing */ - if( execlevel == 0) { + if( execlevel != 0) + break ; + + if( firstlbl != NULL) { line_p glp ; /* line to goto */ - /* grab label to jump to */ + /* grab label to jump to */ eline = token( eline, golabel, sizeof golabel) ; - linlen = strlen( golabel) ; - for( glp = hlp->l_fp ; glp != hlp ; glp = glp->l_fp) { - if( *glp->l_text == '*' - && !strncmp( &glp->l_text[ 1], golabel, linlen)) { + length = strlen( golabel) ; + for( glp = firstlbl ; glp != eolbl ; glp = glp->l_fp) { + char c = *glp->l_text ; + if( (c == '*' || c == ':') + && !strncmp( &glp->l_text[ 1], golabel, length)) { + if( dirnum == DGOSUB) { + caller_p cp = malloc( sizeof *cp) ; + if( cp == NULL) { + status = mloutfail( "OoM on !gosub") ; + break ; + } else { + cp->caller = lp ; + cp->next = returnto ; + returnto = cp ; + } + } + + lp = glp ; break ; } } - if( glp == hlp) { - status = mloutfail( "%%No such label") ; - done = TRUE ; - } else - lp = glp ; - } - - continue ; + if( glp == eolbl) + goto nolabel ; + } else { + nolabel: + status = mloutfail( "%%No such label") ; + } + break ; case DRETURN: /* RETURN directive */ - if( execlevel == 0) - done = TRUE ; + if( execlevel == 0) { + if( returnto != NULL) { + caller_p cp = returnto ; + lp = returnto->caller ; + returnto = returnto->next ; + free( cp) ; + } else { + lp = lp->l_fp ; + done = TRUE ; + } + } - continue ; - - case DENDWHILE: /* ENDWHILE directive */ - if( execlevel) { - --execlevel ; - continue ; - } else { - /* find the right while loop */ - for( whtemp = whlist ; whtemp ; whtemp = whtemp->w_next) - if( whtemp->w_type == BTWHILE - && whtemp->w_end == lp) - break ; - - if( whtemp == NULL) { - status = mloutfail( "%%Internal While loop error") ; - done = TRUE ; - } else - /* reset the line pointer back.. */ - lp = whtemp->w_begin->l_bp ; - - continue ; - } - - case DFORCE: /* FORCE directive */ - force = TRUE ; + break ; + case DFORCE: /* FORCE directive */ + if( execlevel == 0) + docmd( eline) ; /* execute ignoring returned status */ + break ; + default: + status = mloutfail( "%%Unknown Directive") ; } - } + } else if( execlevel == 0) + status = docmd( eline) ; /* execute the statement */ - /* execute the statement */ - status = docmd( eline) ; - if( force) /* force the status */ - status = TRUE ; - - /* check for a command error */ - if( status != TRUE) { - /* look if buffer is showing */ - for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) { - if( wp->w_bufp == bp) { - /* and point it */ - wp->w_dotp = lp ; - wp->w_doto = 0 ; - wp->w_flag |= WFHARD ; - } - } - - /* in any case set the buffer . */ - bp->b_dotp = lp ; - bp->b_doto = 0 ; + if( done || status != TRUE) break ; - } - } + } - execlevel = 0 ; - freewhile( whlist) ; +/* refresh window if buffer is displayed */ + if( bp->b_nwnd) { + for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) { + if( wp->w_bufp == bp) { + /* and point it */ + wp->w_dotp = lp ; + wp->w_doto = 0 ; + wp->w_flag |= WFHARD ; + } + } + } + +/* in any case set the buffer . */ + bp->b_dotp = lp ; + bp->b_doto = 0 ; + + freelist( (list_p) returnto) ; + freelist( (list_p) whlist) ; if( einit) free( einit) ; @@ -896,7 +948,7 @@ static int dobuf( buffer_p bp) { BINDABLE( execfile) { char *fname ; /* name of file to execute */ - int status = newmlarg( &fname, "Execute file: ", 0) ; + int status = newmlarg( &fname, "execute-file: ", 0) ; if( status != TRUE) return status ; @@ -945,21 +997,6 @@ int dofile( const char *fname) { } return status ; -#if 0 - if( status != TRUE) - return status ; - -/* go execute it! */ - status = dobuf( bp) ; - if( status != TRUE) - return status ; - - /* if not displayed, remove the now unneeded buffer and exit */ - if( bp->b_nwnd == 0) - zotbuf( bp) ; - - return TRUE ; -#endif } /* cbuf: diff --git a/exec.h b/exec.h index 1bb6999..48f73c9 100644 --- a/exec.h +++ b/exec.h @@ -12,13 +12,13 @@ boolean gettokval( char *tok, int maxtoksize) ; char *getnewtokval( void) ; /* Bindable functions */ -BINDABLE( execbuf) ; -BINDABLE( execcmd) ; -BINDABLE( execfile) ; -BINDABLE( execproc) ; -BINDABLE( namedcmd) ; -BINDABLE( storemac) ; -BINDABLE( storeproc) ; + BINDABLE( execbuf) ; + BINDABLE( execcmd) ; + BINDABLE( execfile) ; + BINDABLE( execproc) ; + BINDABLE( namedcmd) ; +BBINDABLE( storemac) ; + BINDABLE( storeproc) ; BINDABLE( cbuf1) ; BINDABLE( cbuf2) ; BINDABLE( cbuf3) ; diff --git a/execute.c b/execute.c index 875f91d..55e4cfe 100644 --- a/execute.c +++ b/execute.c @@ -7,12 +7,12 @@ #include #include -#include "estruct.h" -#include "random.h" +#include "defines.h" #include "display.h" #include "file.h" #include "input.h" #include "mlout.h" +#include "random.h" #include "search.h" #include "terminal.h" #include "window.h" @@ -55,10 +55,7 @@ static int inspound( int n) { static int insbrace( int n, int c) { int ch ; /* last character before input */ int oc ; /* caractere oppose a c */ - int i, count ; int target ; /* column brace should go after */ - struct line *oldlp ; - int oldoff ; /* if not called with {, acts as insertion */ if( c == '}') @@ -67,16 +64,17 @@ static int insbrace( int n, int c) { return linsert( n, c) ; /* scan to see if all preceding spaces are white spaces, if not, insert */ - for( i = curwp->w_doto - 1 ; i >= 0 ; --i) { + for( int i = curwp->w_doto - 1 ; i >= 0 ; --i) { ch = lgetc( curwp->w_dotp, i) ; if( ch != ' ' && ch != '\t') return linsert( n, c) ; } - oldlp = curwp->w_dotp ; - oldoff = curwp->w_doto ; +/* save the original cursor position */ + line_p oldlp = curwp->w_dotp ; + int oldoff = curwp->w_doto ; - count = 1 ; + int count = 1 ; do { if( boundary( curwp->w_dotp, curwp->w_doto, REVERSE)) { /* at beginning of buffer, no match to be found */ @@ -132,10 +130,6 @@ static int insbrace( int n, int c) { * char ch; fence type to match against */ static void fmatch( int ch) { - struct line *oldlp ; /* original line pointer */ - int oldoff ; /* and offset */ - struct line *toplp ; /* top line in current window */ - int count ; /* current fence level count */ int opench ; /* open fence */ /* $tpause <= 0 disable fmatch */ @@ -146,8 +140,8 @@ static void fmatch( int ch) { update( FALSE) ; /* save the original cursor position */ - oldlp = curwp->w_dotp ; - oldoff = curwp->w_doto ; + line_p oldlp = curwp->w_dotp ; + int oldoff = curwp->w_doto ; /* setup proper open fence for passed close fence */ if( ch == ')') @@ -158,11 +152,11 @@ static void fmatch( int ch) { opench = '[' ; /* find the top line and set up for scan */ - toplp = curwp->w_linep->l_bp ; + line_p toplp = curwp->w_linep->l_bp ; backchar( FALSE, 1) ; /* . was after the }, move back */ /* scan back until we find it, or reach past the top of the window */ - count = 1 ; + int count = 1 ; /* current fence level count */ do { /* At beginning of window or buffer, no match to be found */ if( curwp->w_dotp == toplp @@ -209,17 +203,14 @@ static void fmatch( int ch) { * int f, n; not used */ BINDABLE( getfence) { - struct line *oldlp; /* original line pointer */ - int oldoff; /* and offset */ int sdir; /* direction of search (1/-1) */ - int count; /* current fence level count */ char ch; /* fence type to match against */ char ofence; /* open fence */ char c; /* current character in scan */ /* save the original cursor position */ - oldlp = curwp->w_dotp; - oldoff = curwp->w_doto; + line_p oldlp = curwp->w_dotp ; + int oldoff = curwp->w_doto ; /* get the current character */ if (oldoff == llength(oldlp)) @@ -259,7 +250,7 @@ BINDABLE( getfence) { } /* scan until we find a match, or reach the end of file */ - count = 1 ; + int count = 1 ; /* current fence level count */ do { if( boundary( curwp->w_dotp, curwp->w_doto, sdir)) { /* at buffer limit, no match to be found */ diff --git a/file.c b/file.c index 40ad584..4190591 100644 --- a/file.c +++ b/file.c @@ -17,7 +17,6 @@ #include "buffer.h" #include "defines.h" #include "display.h" -#include "estruct.h" #include "execute.h" #include "fileio.h" #include "input.h" diff --git a/floodmaz.cmd b/floodmaz.cmd index 5d2d20a..f12b059 100644 --- a/floodmaz.cmd +++ b/floodmaz.cmd @@ -1,35 +1,16 @@ +## floodmaz.cmd -- solve maze by painting wall on the right + # 6 set $seed -execute-file maze.cmd +# either maze.cmd or sharpmaz.cmd +execute-file sharpmaz.cmd set %thisbuf $cbufname - -store-procedure pushxy # push x y - set %x $curcol - set %y $curline - select-buffer stack - beginning-of-file - insert-string %x - newline - insert-string %y - newline - select-buffer %thisbuf -!endm - -store-procedure popxy # pop x y - select-buffer stack - beginning-of-file - set %x $line -1 kill-to-end-of-line - set %y $line -1 kill-to-end-of-line - select-buffer %thisbuf - set $curline %y - set $curcol %x -!endm +set %meml $curline +set %memc $curcol set $curline 1 set $curcol 0 -run pushxy #push stop position +!gosub pushxy #push stop position set %x 1 set $curline 4 set $curcol %x @@ -40,29 +21,47 @@ set %NC &asc "█" set %cc $curcol set %ll $curline set $curcol &add %cc 1 - !if &equ $curchar %OC - run pushxy - !endif + !gosub probe set $curcol &add %cc -1 - !if &equ $curchar %OC - run pushxy - !endif + !gosub probe set $curline &add %ll 1 set $curcol %cc - !if &equ $curchar %OC - run pushxy - !endif + !gosub probe set $curline &add %ll -1 set $curcol %cc - !if &equ $curchar %OC - run pushxy - !endif - run popxy + !gosub probe +# pop x y + select-buffer stack + beginning-of-file + set %x $line +1 kill-to-end-of-line + set %y $line +1 kill-to-end-of-line + select-buffer %thisbuf + set $curline %y + set $curcol %x !endwhile -set $curline 3 -set $curcol 1 + +set $curline %meml +set $curcol %memc select-buffer stack unmark-buffer select-buffer %thisbuf unmark-buffer delete-buffer stack +!return + +:probe + !if ¬ &or &equ $curchar %NC &equ $curchar 32 + :pushxy # push x y + set %x $curcol + set %y $curline + select-buffer stack + beginning-of-file + insert-string %x + newline + insert-string %y + newline + select-buffer %thisbuf + !endif +!return diff --git a/input.c b/input.c index 2367b80..96012f2 100644 --- a/input.c +++ b/input.c @@ -13,8 +13,8 @@ #include #include "bind.h" -#include "estruct.h" #include "bindable.h" +#include "defines.h" #include "display.h" /* rubout(), echos(), echoc(), update() */ #include "exec.h" #include "isa.h" diff --git a/isearch.c b/isearch.c index fb6eddd..6d984b1 100644 --- a/isearch.c +++ b/isearch.c @@ -27,8 +27,8 @@ #include "basic.h" #include "buffer.h" +#include "defines.h" #include "display.h" -#include "estruct.h" #include "exec.h" #include "input.h" #include "line.h" diff --git a/line.c b/line.c index c5939e4..593a87b 100644 --- a/line.c +++ b/line.c @@ -20,7 +20,8 @@ #include #include "buffer.h" -#include "estruct.h" +#include "defines.h" +#include "list.h" #include "mlout.h" #include "utf8.h" #include "window.h" @@ -37,58 +38,46 @@ static int ldelnewline( void) ; * was taken up by the keycode structure). */ -#define KBLOCK 250 /* sizeof kill buffer chunks */ +#define KBLOCK 248 /* sizeof kill buffer chunks */ typedef struct kill { - struct kill *d_next; /* Link to next chunk, NULL if last. */ - char d_chunk[KBLOCK]; /* Deleted text. */ + struct kill *d_next ; /* Link to next chunk, NULL if last. */ + char d_chunk[ KBLOCK] ; /* Deleted text. */ } *kill_p ; static kill_p kbufp = NULL ; /* current kill buffer chunk pointer */ static kill_p kbufh = NULL ; /* kill buffer header pointer */ static int kused = KBLOCK ; /* # of bytes used in kill buffer */ -static int klen ; /* length of kill buffer content */ -static char *value = NULL ; /* temp buffer for value */ +static int klen ; /* length of kill buffer content */ +static char *value = NULL ; /* temp buffer for value */ /* * return some of the contents of the kill buffer */ -char *getkill( void) { - kill_p kp ; - char *cp ; - - if (kbufh == NULL) - /* no kill buffer....just a null string */ +const char *getkill( void) { +/* no kill buffer or no memory .... just return a null string */ + if( kbufh == NULL + || (value = realloc( value, klen + 1)) == NULL) return "" ; - if( value != NULL) - free( value) ; - - value = (char *) malloc( klen + 1) ; - cp = value ; - for( kp = kbufh ; kp != NULL ; kp = kp->d_next) { - int size ; - - if( kp->d_next != NULL) - size = KBLOCK ; - else - size = kused ; - + char *cp = value ; + for( kill_p kp = kbufh ; kp != NULL ; kp = kp->d_next) { + int size = (kp->d_next != NULL) ? KBLOCK : kused ; memcpy( cp, kp->d_chunk, size) ; cp += size ; } *cp = 0 ; - /* and return the constructed value */ - return value; +/* and return the constructed value */ + return value ; } -/* Move the cursor backwards by "n" characters. If "n" is less than zero - call "forwchar" to actually do the move. Otherwise compute the new - cursor location. Error if you try and move out of the buffer. Set the - flag if the line pointer for dot changes. +/* Move the cursor backwards by "n" combined characters. If "n" is less + than zero call "forwchar" to actually do the move. Otherwise compute + the new cursor location. Error if you try and move out of the buffer. + Set the flag if the line pointer for dot changes. */ BBINDABLE( backchar) { assert( f == TRUE || n == 1) ; @@ -105,9 +94,26 @@ BBINDABLE( backchar) { curwp->w_doto = llength( lp) ; curwp->w_flag |= WFMOVE ; } else { - unsigned pos = curwp->w_doto -= 1 ; - if( pos > 0) - curwp->w_doto -= utf8_revdelta( (unsigned char *) &( (curwp->w_dotp)->l_text[ pos]), pos) ; + unsigned pos ; + /* move back over combining unicode */ + combined: + pos = curwp->w_doto -= 1 ; + /* check if at end of unicode */ + if( pos > 0) { + unsigned delta = utf8_revdelta( + (unsigned char *) &( (curwp->w_dotp)->l_text[ pos]), pos) ; + if( delta != 0) { + pos = curwp->w_doto -= delta ; + if( pos > 0) { /* check if on combining unicode */ + unicode_t unc ; + + utf8_to_unicode( curwp->w_dotp->l_text, pos, + llength( curwp->w_dotp), &unc) ; + if( utf8_width( unc) == 0) + goto combined ; + } + } + } } } @@ -115,10 +121,11 @@ BBINDABLE( backchar) { } -/* Move the cursor forwards by "n" characters. If "n" is less than zero - call "backchar" to actually do the move. Otherwise compute the new - cursor location, and move ".". Error if you try and move off the end of - the buffer. Set the flag if the line pointer for dot changes. +/* Move the cursor forwards by "n" combined characters. If "n" is less + than zero call "backchar" to actually do the move. Otherwise compute + the new cursor location, and move ".". Error if you try and move off + the end of the buffer. Set the flag if the line pointer for dot + changes. */ BBINDABLE( forwchar) { assert( f == TRUE || n == 1) ; @@ -140,7 +147,7 @@ BBINDABLE( forwchar) { curwp->w_doto += utf8_to_unicode( curwp->w_dotp->l_text, curwp->w_doto, len, &unc) ; /* check if next char is null width unicode */ - while( curwp->w_doto != len) { + while( curwp->w_doto < len - 1) { unsigned bytes = utf8_to_unicode( curwp->w_dotp->l_text, curwp->w_doto, len, &unc) ; if( utf8_width( unc) == 0) @@ -154,8 +161,8 @@ BBINDABLE( forwchar) { return TRUE ; } -/* - * This routine allocates a block of memory large enough to hold a struct line + +/* This routine allocates a block of memory large enough to hold a struct line * containing "used" characters. The block is always rounded up a bit. Return * a pointer to the new block, or NULL if there isn't any memory left. Print a * message in the message line if no space. @@ -163,13 +170,13 @@ BBINDABLE( forwchar) { line_p lalloc( int used) { #define BLOCK_SIZE 16 /* Line block chunk size. */ -/* rounding down use masking instead or modulo when BLOCK_SIZE is power of 2 */ +/* rounding down use masking instead of modulo when BLOCK_SIZE is power of 2 */ #if (BLOCK_SIZE & -BLOCK_SIZE) == BLOCK_SIZE int size = (used + BLOCK_SIZE) & ~(BLOCK_SIZE - 1) ; #else int size = used + BLOCK_SIZE - used % BLOCK_SIZE ; #endif - line_p lp = (line_p) malloc( offsetof( struct line, l_text) + size) ; + line_p lp = malloc( sizeof *lp + size) ; if( lp == NULL) mloutstr( "(OUT OF MEMORY)") ; else { @@ -180,76 +187,70 @@ line_p lalloc( int used) { return lp ; } -/* - * Delete line "lp". Fix all of the links that might point at it (they are + +/* Delete line "lp". Fix all of the links that might point at it (they are * moved to offset 0 of the next line. Unlink the line from whatever buffer it * might be in. Release the memory. The buffers are updated too; the magic * conditions described in the above comments don't hold here. */ void lfree( line_p lp) { - buffer_p bp; - struct window *wp; + for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) { + if( wp->w_linep == lp) + wp->w_linep = lp->l_fp ; - wp = wheadp; - while (wp != NULL) { - if (wp->w_linep == lp) - wp->w_linep = lp->l_fp; - if (wp->w_dotp == lp) { - wp->w_dotp = lp->l_fp; - wp->w_doto = 0; + if( wp->w_dotp == lp) { + wp->w_dotp = lp->l_fp ; + wp->w_doto = 0 ; } - if (wp->w_markp == lp) { - wp->w_markp = lp->l_fp; - wp->w_marko = 0; + + if( wp->w_markp == lp) { + wp->w_markp = lp->l_fp ; + wp->w_marko = 0 ; } - wp = wp->w_wndp; } - bp = bheadp; - while (bp != NULL) { - if (bp->b_nwnd == 0) { - if (bp->b_dotp == lp) { - bp->b_dotp = lp->l_fp; - bp->b_doto = 0; + + for( buffer_p bp = bheadp ; bp != NULL ; bp = bp->b_bufp) { + if( bp->b_nwnd == 0) { + if( bp->b_dotp == lp) { + bp->b_dotp = lp->l_fp ; + bp->b_doto = 0 ; } - if (bp->b_markp == lp) { - bp->b_markp = lp->l_fp; - bp->b_marko = 0; + + if( bp->b_markp == lp) { + bp->b_markp = lp->l_fp ; + bp->b_marko = 0 ; } } - bp = bp->b_bufp; } - lp->l_bp->l_fp = lp->l_fp; - lp->l_fp->l_bp = lp->l_bp; - free((char *) lp); + + lp->l_bp->l_fp = lp->l_fp ; + lp->l_fp->l_bp = lp->l_bp ; + free( lp) ; } -/* - * This routine gets called when a character is changed in place in the current + +/* This routine gets called when a character is changed in place in the current * buffer. It updates all of the required flags in the buffer and window * system. The flag used is passed as an argument; if the buffer is being - * displayed in more than 1 window we change EDIT t HARD. Set MODE if the + * displayed in more than 1 window we change EDIT to HARD. Set MODE if the * mode line needs to be updated (the "*" has to be set). */ -void lchange(int flag) -{ - struct window *wp; +void lchange( int flag) { + if( curbp->b_nwnd != 1) /* Ensure hard. */ + flag = WFHARD ; - if (curbp->b_nwnd != 1) /* Ensure hard. */ - flag = WFHARD; - if ((curbp->b_flag & BFCHG) == 0) { /* First change, so */ - flag |= WFMODE; /* update mode lines. */ - curbp->b_flag |= BFCHG; - } - wp = wheadp; - while (wp != NULL) { - if (wp->w_bufp == curbp) - wp->w_flag |= flag; - wp = wp->w_wndp; + if( (curbp->b_flag & BFCHG) == 0) { /* First change, so */ + flag |= WFMODE ; /* update mode lines. */ + curbp->b_flag |= BFCHG ; } + + for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) + if( wp->w_bufp == curbp) + wp->w_flag |= flag ; } -/* - * insert spaces forward into text + +/* insert spaces forward into text * * int f, n; default flag and numeric argument */ @@ -260,24 +261,18 @@ BINDABLE( insspace) { return TRUE ; } -/* - * linstr -- Insert a string at the current point - */ - -int linstr( char *instr) { - int status = TRUE ; +/* linstr -- Insert a string at the current point */ +boolean linstr( char *instr) { + boolean status = TRUE ; if( instr != NULL) { - unicode_t tmpc ; + int c ; - while( (tmpc = *instr++ & 0xFF)) { - status = - (tmpc == '\n' ? lnewline() : (int) linsert_byte( 1, tmpc)) ; - - /* Insertion error? */ - if( status != TRUE) { + while( (c = (unsigned char) *instr++)) { + status = (c == '\n') ? lnewline() : linsert_byte( 1, c) ; + if( status != TRUE) { /* Insertion error? */ mloutstr( "%Out of memory while inserting") ; - return status ; + break ; } } } @@ -298,84 +293,88 @@ int linstr( char *instr) { boolean linsert_byte( int n, int c) { char *cp1; char *cp2; - line_p lp1, lp2, lp3 ; - int doto; - int i; - struct window *wp; + line_p lp2, lp3 ; + int i ; assert( (curbp->b_mode & MDVIEW) == 0) ; - lchange(WFEDIT); - lp1 = curwp->w_dotp; /* Current line */ - if (lp1 == curbp->b_linep) { /* At the end: special */ - if (curwp->w_doto != 0) { - mloutstr( "bug: linsert") ; - return FALSE; - } + lchange( WFEDIT) ; + line_p lp1 = curwp->w_dotp ; /* Current line */ + if( lp1 == curbp->b_linep) { /* At the end: special */ + if( curwp->w_doto != 0) + return mloutfail( "bug: linsert") ; lp2 = lalloc( n) ; /* Allocate new line */ if( lp2 == NULL) return FALSE ; - lp3 = lp1->l_bp; /* Previous line */ - lp3->l_fp = lp2; /* Link in */ - lp2->l_fp = lp1; - lp1->l_bp = lp2; - lp2->l_bp = lp3; - for (i = 0; i < n; ++i) - lp2->l_text[i] = c; - curwp->w_dotp = lp2; - curwp->w_doto = n; - return TRUE; + lp3 = lp1->l_bp ; /* Previous line */ + lp3->l_fp = lp2 ; /* Link in */ + lp2->l_fp = lp1 ; + lp1->l_bp = lp2 ; + lp2->l_bp = lp3 ; + for( i = 0 ; i < n ; ++i) + lp2->l_text[ i] = c ; + + curwp->w_dotp = lp2 ; + curwp->w_doto = n ; + return TRUE ; } - doto = curwp->w_doto; /* Save for later. */ - if (lp1->l_used + n > lp1->l_size) { /* Hard: reallocate */ + + int doto = curwp->w_doto ; /* Save for later. */ + if( lp1->l_used + n > lp1->l_size) { /* Hard: reallocate */ lp2 = lalloc( lp1->l_used + n) ; if( lp2 == NULL) return FALSE ; - cp1 = &lp1->l_text[0]; - cp2 = &lp2->l_text[0]; - while (cp1 != &lp1->l_text[doto]) - *cp2++ = *cp1++; - cp2 += n; - while (cp1 != &lp1->l_text[lp1->l_used]) - *cp2++ = *cp1++; - lp1->l_bp->l_fp = lp2; - lp2->l_fp = lp1->l_fp; - lp1->l_fp->l_bp = lp2; - lp2->l_bp = lp1->l_bp; - free((char *) lp1); + cp1 = &lp1->l_text[ 0] ; + cp2 = &lp2->l_text[ 0] ; + while( cp1 != &lp1->l_text[ doto]) + *cp2++ = *cp1++ ; + + cp2 += n ; + while( cp1 != &lp1->l_text[ lp1->l_used]) + *cp2++ = *cp1++ ; + + lp1->l_bp->l_fp = lp2 ; + lp2->l_fp = lp1->l_fp ; + lp1->l_fp->l_bp = lp2 ; + lp2->l_bp = lp1->l_bp ; + free( lp1) ; } else { /* Easy: in place */ - lp2 = lp1; /* Pretend new line */ - lp2->l_used += n; - cp2 = &lp1->l_text[lp1->l_used]; - cp1 = cp2 - n; - while (cp1 != &lp1->l_text[doto]) - *--cp2 = *--cp1; + lp2 = lp1 ; /* Pretend new line */ + lp2->l_used += n ; + cp2 = &lp1->l_text[ lp1->l_used] ; + cp1 = cp2 - n ; + while( cp1 != &lp1->l_text[ doto]) + *--cp2 = *--cp1 ; } - for (i = 0; i < n; ++i) /* Add the characters */ - lp2->l_text[doto + i] = c; - wp = wheadp; /* Update windows */ - while (wp != NULL) { - if (wp->w_linep == lp1) - wp->w_linep = lp2; - if (wp->w_dotp == lp1) { - wp->w_dotp = lp2; - if (wp == curwp || wp->w_doto > doto) - wp->w_doto += n; + + for( i = 0 ; i < n ; ++i) /* Add the characters */ + lp2->l_text[ doto + i] = c ; + +/* Update windows */ + for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) { + if( wp->w_linep == lp1) + wp->w_linep = lp2 ; + + if( wp->w_dotp == lp1) { + wp->w_dotp = lp2 ; + if( wp == curwp || wp->w_doto > doto) + wp->w_doto += n ; } - if (wp->w_markp == lp1) { - wp->w_markp = lp2; - if (wp->w_marko > doto) - wp->w_marko += n; + + if( wp->w_markp == lp1) { + wp->w_markp = lp2 ; + if( wp->w_marko > doto) + wp->w_marko += n ; } - wp = wp->w_wndp; } - return TRUE; + + return TRUE ; } -int linsert( int n, unicode_t c) { +boolean linsert( int n, unicode_t c) { assert( n >= 0) ; assert( !(curbp->b_mode & MDVIEW)) ; @@ -403,7 +402,7 @@ int linsert( int n, unicode_t c) { * * int c ; character to overwrite on current position */ -static int lowrite( int c) { +static boolean lowrite( int c) { if( curwp->w_doto < curwp->w_dotp->l_used && ( lgetc( curwp->w_dotp, curwp->w_doto) != '\t' || (curwp->w_doto % tabwidth) == (tabwidth - 1) @@ -413,20 +412,18 @@ static int lowrite( int c) { return linsert( 1, c) ; } -/* - * lover -- Overwrite a string at the current point - */ -int lover( char *ostr) { - int status = TRUE ; +/* lover -- Overwrite a string at the current point */ +boolean lover( char *ostr) { + boolean status = TRUE ; if( ostr != NULL) { - char tmpc ; + int c ; - while( (tmpc = *ostr++)) { - status = (tmpc == '\n' ? lnewline() : lowrite( tmpc)) ; + while( (c = (unsigned char) *ostr++)) { + status = (c == '\n') ? lnewline() : lowrite( c) ; if( status != TRUE) { /* Insertion error? */ mloutstr( "%Out of memory while overwriting") ; - return status ; + break ; } } } @@ -434,21 +431,15 @@ int lover( char *ostr) { return status ; } -/* - * Insert a newline into the buffer at the current location of dot in the - * current window. The funny ass-backwards way it does things is not a botch; - * it just makes the last line in the file not a special case. Return TRUE if - * everything works out and FALSE on error (memory allocation failure). The - * update of dot and mark is a bit easier then in the above case, because the - * split forces more updating. - */ -int lnewline( void) { - char *cp1; - char *cp2; - line_p lp1, lp2 ; - int doto; - struct window *wp; +/* Insert a newline into the buffer at the current location of dot in the + current window. The funny ass-backwards way it does things is not a + botch; it just makes the last line in the file not a special case. + Return TRUE if everything works out and FALSE on error (memory + allocation failure). The update of dot and mark is a bit easier then in + the above case, because the split forces more updating. + */ +boolean lnewline( void) { assert( !(curbp->b_mode & MDVIEW)) ; #if SCROLLCODE @@ -456,75 +447,104 @@ int lnewline( void) { #else lchange(WFHARD); #endif - lp1 = curwp->w_dotp; /* Get the address and */ - doto = curwp->w_doto; /* offset of "." */ - lp2 = lalloc( doto) ; /* New first half line */ + line_p lp1 = curwp->w_dotp ; /* Get the address and */ + int doto = curwp->w_doto ; /* offset of "." */ + line_p lp2 = lalloc( doto) ; /* New first half line */ if( lp2 == NULL) return FALSE ; - cp1 = &lp1->l_text[0]; /* Shuffle text around */ - cp2 = &lp2->l_text[0]; - while (cp1 != &lp1->l_text[doto]) - *cp2++ = *cp1++; - cp2 = &lp1->l_text[0]; - while (cp1 != &lp1->l_text[lp1->l_used]) - *cp2++ = *cp1++; - lp1->l_used -= doto; - lp2->l_bp = lp1->l_bp; - lp1->l_bp = lp2; - lp2->l_bp->l_fp = lp2; - lp2->l_fp = lp1; - wp = wheadp; /* Windows */ - while (wp != NULL) { - if (wp->w_linep == lp1) - wp->w_linep = lp2; - if (wp->w_dotp == lp1) { - if (wp->w_doto < doto) - wp->w_dotp = lp2; + memcpy( lp2->l_text, lp1->l_text, doto) ; + lp1->l_used -= doto ; + memcpy( lp1->l_text, &lp1->l_text[ doto], lp1->l_used) ; + lp2->l_fp = lp1 ; + lp2->l_bp = lp1->l_bp ; + lp1->l_bp = lp2 ; + lp2->l_bp->l_fp = lp2 ; + for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) { + if( wp->w_linep == lp1) + wp->w_linep = lp2 ; + + if( wp->w_dotp == lp1) { + if( wp->w_doto < doto) + wp->w_dotp = lp2 ; else - wp->w_doto -= doto; + wp->w_doto -= doto ; } + if (wp->w_markp == lp1) { - if (wp->w_marko < doto) - wp->w_markp = lp2; + if( wp->w_marko < doto) + wp->w_markp = lp2 ; else - wp->w_marko -= doto; + wp->w_marko -= doto ; } - wp = wp->w_wndp; } - return TRUE; + + return TRUE ; } -int lgetchar( unicode_t *c) { - if( curwp->w_dotp->l_used == curwp->w_doto) { - *c = (curbp->b_mode & MDDOS) ? '\r' : '\n' ; + +/* lgetchar(): + * get unicode value and return UTF-8 size of character at dot. + */ +int lgetchar( unicode_t *cp) { + if( curwp->w_dotp->l_used == curwp->w_doto) { /* at EOL? */ + *cp = (curbp->b_mode & MDDOS) ? '\r' : '\n' ; return 1 ; } else return utf8_to_unicode( curwp->w_dotp->l_text, curwp->w_doto, - llength( curwp->w_dotp), c) ; + llength( curwp->w_dotp), cp) ; } -/* + +/* lcombinedsize(): + * return total UTF-8 size of combined character at dot. + */ +static int lcombinedsize( void) { + if( curwp->w_dotp->l_used == curwp->w_doto) /* EOL? */ + return 1 ; + else { + unicode_t c ; + + int pos = curwp->w_doto ; + unsigned bytes = utf8_to_unicode( curwp->w_dotp->l_text, pos, + llength( curwp->w_dotp), &c) ; + /* check if followed by combining unicode character */ + pos += bytes ; + while( pos < llength( curwp->w_dotp) - 1) { /* at least 2 bytes */ + unsigned cnt = utf8_to_unicode( curwp->w_dotp->l_text, pos, + llength( curwp->w_dotp), &c) ; + if( utf8_width( c) == 0) { + bytes += cnt ; + pos += cnt ; + } else + break ; + } + + return bytes ; + } +} + + +/* ldelchar(): + * delete forward combined characters starting at dot. + * * ldelete() really fundamentally works on bytes, not characters. * It is used for things like "scan 5 words forwards, and remove * the bytes we scanned". * * If you want to delete characters, use ldelchar(). */ -boolean ldelchar( long n, boolean kflag) { +boolean ldelchar( long n, boolean kill_f) { /* testing for read only mode is done by ldelete() */ - while( n-- > 0) { - unicode_t c; - - if( !ldelete( lgetchar( &c), kflag)) + while( n-- > 0) + if( !ldelete( lcombinedsize(), kill_f)) return FALSE ; - } return TRUE ; } -/* - * This function deletes "n" bytes, starting at dot. It understands how do deal + +/* This function deletes "n" bytes, starting at dot. It understands how do deal * with end of lines, etc. It returns TRUE if all of the characters were * deleted, and FALSE if they were not (because dot ran into the end of the * buffer. The "kflag" is TRUE if the text should be put in the kill buffer. @@ -533,101 +553,72 @@ boolean ldelchar( long n, boolean kflag) { * int kflag; put killed text in kill buffer flag */ boolean ldelete( long n, boolean kflag) { - char *cp1; - char *cp2; - line_p dotp; - int doto; - int chunk; - struct window *wp; - assert( !(curbp->b_mode & MDVIEW)) ; while( n > 0) { - dotp = curwp->w_dotp; - doto = curwp->w_doto; - if (dotp == curbp->b_linep) /* Hit end of buffer. */ - return FALSE; - chunk = dotp->l_used - doto; /* Size of chunk. */ - if (chunk > n) - chunk = n; - if (chunk == 0) { /* End of line, merge. */ + line_p dotp = curwp->w_dotp ; + if( dotp == curbp->b_linep) /* Hit end of buffer. */ + return FALSE ; + + int doto = curwp->w_doto ; + int chunk = dotp->l_used - doto ; /* Size of chunk. */ + if( chunk == 0) { /* End of line, merge. */ #if SCROLLCODE - lchange(WFHARD | WFKILLS); + lchange( WFHARD | WFKILLS) ; #else - lchange(WFHARD); + lchange( WFHARD) ; #endif - if (ldelnewline() == FALSE - || (kflag != FALSE && kinsert('\n') == FALSE)) - return FALSE; - --n; - continue; - } - lchange(WFEDIT); - cp1 = &dotp->l_text[doto]; /* Scrunch text. */ - cp2 = cp1 + chunk; - if (kflag != FALSE) { /* Kill? */ - while (cp1 != cp2) { - if (kinsert(*cp1) == FALSE) - return FALSE; - ++cp1; - } - cp1 = &dotp->l_text[doto]; - } - while (cp2 != &dotp->l_text[dotp->l_used]) - *cp1++ = *cp2++; - dotp->l_used -= chunk; - wp = wheadp; /* Fix windows */ - while (wp != NULL) { - if (wp->w_dotp == dotp && wp->w_doto >= doto) { - wp->w_doto -= chunk; - if (wp->w_doto < doto) - wp->w_doto = doto; - } - if (wp->w_markp == dotp && wp->w_marko >= doto) { - wp->w_marko -= chunk; - if (wp->w_marko < doto) - wp->w_marko = doto; - } - wp = wp->w_wndp; - } - n -= chunk; - } - return TRUE; -} + if( ldelnewline() == FALSE + || (kflag != FALSE && kinsert( '\n') == FALSE)) + return FALSE ; -/* - * getctext: grab and return a string with the text of - * the current line - */ -char *getctext( void) { - line_p lp ; /* line to copy */ - int size; /* length of line to return */ - static int rsize = 0 ; - static char *rline ; /* line to return */ + --n ; + continue ; + } else if( chunk > n) + chunk = n ; - /* find the contents of the current line and its length */ - lp = curwp->w_dotp; - size = lp->l_used; - if( size >= rsize) { - if( rsize) - free( rline) ; + lchange( WFEDIT) ; + char *cp1 = &dotp->l_text[ doto] ; /* Scrunch text. */ + char *cp2 = cp1 + chunk ; + if( kflag != FALSE) { /* Kill? */ + while( cp1 != cp2) { + if( kinsert( *cp1) == FALSE) + return FALSE ; + + ++cp1 ; + } - rsize = size + 1 ; - rline = malloc( rsize) ; - if( rline == NULL) { - rsize = 0 ; - return "" ; + cp1 = &dotp->l_text[ doto] ; } + + while( cp2 != &dotp->l_text[ dotp->l_used]) + *cp1++ = *cp2++ ; + + dotp->l_used -= chunk ; + + /* Fix windows */ + for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) { + if( wp->w_dotp == dotp && wp->w_doto >= doto) { + wp->w_doto -= chunk ; + if( wp->w_doto < doto) + wp->w_doto = doto ; + } + + if( wp->w_markp == dotp && wp->w_marko >= doto) { + wp->w_marko -= chunk ; + if( wp->w_marko < doto) + wp->w_marko = doto ; + } + } + + n -= chunk ; } - /* copy it across */ - memcpy( rline, lp->l_text, size) ; - rline[ size] = 0 ; - return rline ; + return TRUE ; } -/* - * Delete a newline. Join the current line with the next line. If the next line + +/* Delete a newline. Join the current line with the next line. If the next line * is the magic header line always return TRUE; merging the last line with the * header line can be thought of as always being a successful operation, even * if nothing is done, and this makes the kill buffer work "right". Easy cases @@ -638,104 +629,101 @@ char *getctext( void) { static int ldelnewline( void) { char *cp1; char *cp2; - line_p lp1, lp2, lp3 ; - struct window *wp; + window_p wp ; assert( (curbp->b_mode & MDVIEW) == 0) ; - lp1 = curwp->w_dotp; - lp2 = lp1->l_fp; - if (lp2 == curbp->b_linep) { /* At the buffer end. */ - if (lp1->l_used == 0) /* Blank line. */ - lfree(lp1); - return TRUE; + line_p lp1 = curwp->w_dotp ; + line_p lp2 = lp1->l_fp ; + if( lp2 == curbp->b_linep) { /* At the buffer end. */ + if( lp1->l_used == 0) /* Blank line. */ + lfree( lp1) ; + + return TRUE ; } - if (lp2->l_used <= lp1->l_size - lp1->l_used) { - cp1 = &lp1->l_text[lp1->l_used]; - cp2 = &lp2->l_text[0]; - while (cp2 != &lp2->l_text[lp2->l_used]) - *cp1++ = *cp2++; - wp = wheadp; - while (wp != NULL) { - if (wp->w_linep == lp2) - wp->w_linep = lp1; - if (wp->w_dotp == lp2) { - wp->w_dotp = lp1; - wp->w_doto += lp1->l_used; + + if( lp2->l_used <= lp1->l_size - lp1->l_used) { + cp1 = &lp1->l_text[ lp1->l_used] ; + cp2 = lp2->l_text ; + while( cp2 != &lp2->l_text[ lp2->l_used]) + *cp1++ = *cp2++ ; + + for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) { + if( wp->w_linep == lp2) + wp->w_linep = lp1 ; + + if( wp->w_dotp == lp2) { + wp->w_dotp = lp1 ; + wp->w_doto += lp1->l_used ; } - if (wp->w_markp == lp2) { - wp->w_markp = lp1; - wp->w_marko += lp1->l_used; + + if( wp->w_markp == lp2) { + wp->w_markp = lp1 ; + wp->w_marko += lp1->l_used ; } - wp = wp->w_wndp; } - lp1->l_used += lp2->l_used; - lp1->l_fp = lp2->l_fp; - lp2->l_fp->l_bp = lp1; - free((char *) lp2); - return TRUE; + + lp1->l_used += lp2->l_used ; + lp1->l_fp = lp2->l_fp ; + lp2->l_fp->l_bp = lp1 ; + free( lp2) ; + return TRUE ; } - lp3 = lalloc( lp1->l_used + lp2->l_used) ; + line_p lp3 = lalloc( lp1->l_used + lp2->l_used) ; if( lp3 == NULL) return FALSE ; - cp1 = &lp1->l_text[0]; - cp2 = &lp3->l_text[0]; - while (cp1 != &lp1->l_text[lp1->l_used]) - *cp2++ = *cp1++; - cp1 = &lp2->l_text[0]; - while (cp1 != &lp2->l_text[lp2->l_used]) - *cp2++ = *cp1++; - lp1->l_bp->l_fp = lp3; - lp3->l_fp = lp2->l_fp; - lp2->l_fp->l_bp = lp3; - lp3->l_bp = lp1->l_bp; - wp = wheadp; - while (wp != NULL) { - if (wp->w_linep == lp1 || wp->w_linep == lp2) - wp->w_linep = lp3; - if (wp->w_dotp == lp1) - wp->w_dotp = lp3; - else if (wp->w_dotp == lp2) { - wp->w_dotp = lp3; - wp->w_doto += lp1->l_used; + cp1 = lp1->l_text ; + cp2 = lp3->l_text ; + while( cp1 != &lp1->l_text[ lp1->l_used]) + *cp2++ = *cp1++ ; + + cp1 = lp2->l_text ; + while( cp1 != &lp2->l_text[ lp2->l_used]) + *cp2++ = *cp1++ ; + + lp1->l_bp->l_fp = lp3 ; + lp3->l_fp = lp2->l_fp ; + lp2->l_fp->l_bp = lp3 ; + lp3->l_bp = lp1->l_bp ; + for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) { + if( wp->w_linep == lp1 || wp->w_linep == lp2) + wp->w_linep = lp3 ; + + if( wp->w_dotp == lp1) + wp->w_dotp = lp3 ; + else if( wp->w_dotp == lp2) { + wp->w_dotp = lp3 ; + wp->w_doto += lp1->l_used ; } - if (wp->w_markp == lp1) - wp->w_markp = lp3; - else if (wp->w_markp == lp2) { - wp->w_markp = lp3; - wp->w_marko += lp1->l_used; + + if( wp->w_markp == lp1) + wp->w_markp = lp3 ; + else if( wp->w_markp == lp2) { + wp->w_markp = lp3 ; + wp->w_marko += lp1->l_used ; } - wp = wp->w_wndp; } - free((char *) lp1); - free((char *) lp2); - return TRUE; + + free( lp1) ; + free( lp2) ; + return TRUE ; } -/* - * Delete all of the text saved in the kill buffer. Called by commands when a + +/* Delete all of the text saved in the kill buffer. Called by commands when a * new kill context is being created. The kill buffer array is released, just * in case the buffer has grown to immense size. No errors. */ -void kdelete(void) -{ - kill_p kp; /* ptr to scan kill buffer chunk list */ +void kdelete( void) { + if( kbufh != NULL) { + /* first, delete all the chunks */ + freelist( (list_p) kbufh) ; - if (kbufh != NULL) { - - /* first, delete all the chunks */ - kbufp = kbufh; - while (kbufp != NULL) { - kp = kbufp->d_next; - free(kbufp); - kbufp = kp; - } - - /* and reset all the kill buffer pointers */ - kbufh = kbufp = NULL; - kused = KBLOCK; + /* and reset all the kill buffer pointers */ + kbufh = kbufp = NULL ; + kused = KBLOCK ; klen = 0 ; if( value != NULL) { free( value) ; diff --git a/line.h b/line.h index 0dc78e3..4434f49 100644 --- a/line.h +++ b/line.h @@ -14,11 +14,11 @@ list of marks into the line. */ typedef struct line { - struct line *l_fp ; /* Forward link to the next line */ - struct line *l_bp ; /* Backward link to the previous line */ - int l_size ; /* Allocated size */ - int l_used ; /* Used size */ - char l_text[ 1] ; /* A bunch of characters */ + struct line *l_fp ; /* Forward link to the next line */ + struct line *l_bp ; /* Backward link to the previous line */ + int l_size ; /* Allocated size */ + int l_used ; /* Used size */ + char l_text[] ; /* A bunch of characters */ } *line_p ; #define lforw(lp) ((lp)->l_fp) @@ -29,28 +29,26 @@ typedef struct line { extern int tabwidth ; /* Map to $tab, default to 8, can be set to [1, .. */ -char *getkill( void) ; - /* Bindable functions */ BBINDABLE( backchar) ; BBINDABLE( forwchar) ; BINDABLE( insspace) ; BINDABLE( yank) ; -void lfree( line_p lp) ; void lchange( int flag) ; -int linstr( char *instr) ; -int linsert( int n, unicode_t c) ; +boolean linstr( char *instr) ; +boolean linsert( int n, unicode_t c) ; boolean linsert_byte( int n, int c) ; -int lover( char *ostr) ; -int lnewline( void) ; +boolean lover( char *ostr) ; +boolean lnewline( void) ; boolean ldelete( long n, boolean kflag) ; boolean ldelchar( long n, boolean kflag) ; int lgetchar( unicode_t *cref) ; -char *getctext( void) ; void kdelete( void) ; int kinsert( int c) ; -line_p lalloc( int minsize) ; /* Allocate a line of at least minsize chars. */ +line_p lalloc( int minsize) ; /* Allocate a line of at least minsize chars. */ +void lfree( line_p lp) ; /* free a line, updating buffers and windows */ +const char *getkill( void) ; /* get value of $kill */ boolean rdonly( void) ; /* Read Only error message */ diff --git a/list.c b/list.c new file mode 100644 index 0000000..bee2b11 --- /dev/null +++ b/list.c @@ -0,0 +1,16 @@ +/* list.c -- implements list.h */ +/* Copyright © 2021 Renaud Fivet */ +#include "list.h" + +#include /* free() */ + +/* free a list */ +void freelist( list_p lp) { + while( lp) { + list_p next = lp->next ; + free( lp) ; + lp = next ; + } +} + +/* end of list.c */ diff --git a/list.h b/list.h new file mode 100644 index 0000000..718fa47 --- /dev/null +++ b/list.h @@ -0,0 +1,13 @@ +/* list.h -- generic list deletion */ +/* Copyright © 2021 Renaud Fivet */ +#ifndef _LIST_H_ +#define _LIST_H_ + +typedef struct list { + struct list *next ; +} *list_p ; + +void freelist( list_p lp) ; + +#endif +/* end of list.h */ diff --git a/lock.h b/lock.h index 9b82e91..e100935 100644 --- a/lock.h +++ b/lock.h @@ -2,7 +2,7 @@ #ifndef _LOCK_H_ #define _LOCK_H_ -#include "estruct.h" +#include "defines.h" /* BSD, SVR4 */ #if BSD | SVR4 int lockchk( const char *fname) ; diff --git a/main.c b/main.c index 71a35f4..413dad1 100644 --- a/main.c +++ b/main.c @@ -62,14 +62,13 @@ * */ -#include #include #include #include -#include "estruct.h" /* Global structures and defines. */ +#include "defines.h" /* OS specific customization */ #if UNIX -#include +# include #endif #include "basic.h" @@ -91,9 +90,8 @@ #include "window.h" #if UNIX -static void emergencyexit(int signr) -{ - quickexit(FALSE, 0); +static void emergencyexit( int signr) { + quickexit( FALSE, 0) ; quit( TRUE, 0) ; /* If quickexit fails (to save changes), do a force quit */ } #endif @@ -124,13 +122,12 @@ static void usage( void) { } -int main(int argc, char **argv) -{ - struct buffer *bp; /* temp buffer pointer */ +int main( int argc, char *argv[]) { + buffer_p bp; /* temp buffer pointer */ int firstfile; /* first file flag */ int carg; /* current arg to scan */ int startflag; /* startup executed flag */ - struct buffer *firstbp = NULL; /* ptr to first buffer in cmd line */ + buffer_p firstbp = NULL; /* ptr to first buffer in cmd line */ int viewflag; /* are we starting in view mode? */ int gotoflag; /* do we need to goto a line at start? */ int gline = 0; /* if so, what line? */ @@ -138,17 +135,10 @@ int main(int argc, char **argv) int errflag; /* C error processing? */ bname_t bname ; /* buffer name of file to read */ - setlocale( LC_CTYPE, "") ; /* expects $LANG like en_GB.UTF-8 */ - #if PKCODE & BSD sleep(1); /* Time for window manager. */ #endif -#if UNIX -#ifdef SIGWINCH - signal(SIGWINCH, sizesignal); -#endif -#endif if( argc == 2) { if( strcmp( argv[ 1], "--help") == 0) { usage() ; @@ -325,7 +315,7 @@ int main(int argc, char **argv) */ static void edinit( char *bname) { buffer_p bp; - struct window *wp; + window_p wp; if( !init_bindings() /* initialize mapping of function to name and key */ || NULL == (bp = bfind( bname, TRUE, 0)) /* First buffer */ @@ -357,80 +347,67 @@ static void edinit( char *bname) { wp->w_flag = WFMODE | WFHARD; /* Full. */ } + /***** Compiler specific Library functions ****/ -#if RAMSIZE -/* These routines will allow me to track memory usage by placing - a layer on top of the standard system malloc() and free() calls. - with this code defined, the environment variable, $RAM, will - report on the number of bytes allocated via malloc. +#if RAMSIZE - with SHOWRAM defined, the number is also posted on the - end of the bottom mode line and is updated whenever it is changed. +/* These routines will allow me to track memory usage by placing a layer on + top of the standard system malloc() and free() calls. with this code + defined, the environment variable, $RAM, will report on the number of + bytes allocated via malloc. + + with SHOWRAM defined, the number is also posted on the end of the bottom + mode line and is updated whenever it is changed. */ -static void dspram( void) ; - -#undef malloc -#undef free -#if 0 -char *allocate(nbytes) - /* allocate nbytes and track */ -unsigned nbytes; /* # of bytes to allocate */ -#endif -void *allocate( size_t nbytes) -{ - char *mp; /* ptr returned from malloc */ -/* char *malloc(); */ - - mp = malloc(nbytes); - if (mp) { - envram += nbytes; #if RAMSHOW - dspram(); + static void dspram( void) ; +#endif + +void *allocate( size_t nbytes) { + nbytes += sizeof nbytes ; /* add overhead to track allocation */ + size_t *mp = (malloc)( nbytes) ; /* call the function not the macro */ + if( mp) { + *mp++ = nbytes ; + envram += nbytes ; +#if RAMSHOW + dspram() ; #endif } - return mp; + return mp ; } -#if 0 -release(mp) - /* release malloced memory and track */ -char *mp; /* chunk of RAM to release */ -#endif -void release( void *mp) -{ - unsigned *lp; /* ptr to the long containing the block size */ - - if (mp) { +void release( void *mp) { + if( mp) { + size_t *sp = mp ; + sp-- ; /* update amount of ram currently malloced */ - lp = ((unsigned *) mp) - 1; - envram -= (long) *lp - 2; - free(mp); + envram -= *sp ; + (free)( sp) ; /* call the function not the macro */ #if RAMSHOW - dspram(); + dspram() ; #endif } } #if RAMSHOW -static void dspram( void) -{ /* display the amount of RAM currently malloced */ - char mbuf[20]; - char *sp; +static void dspram( void) { /* display the amount of RAM currently malloced */ + char mbuf[ 20] ; - TTmove(term.t_nrow - 1, 70); + TTmove( term.t_nrow, term.t_ncol - 12) ; #if COLOR - TTforg(7); - TTbacg(0); + TTforg( 7) ; + TTbacg(0) ; #endif - sprintf(mbuf, "[%lu]", envram); - sp = &mbuf[0]; - while (*sp) - TTputc(*sp++); - TTmove(term.t_nrow, 0); - movecursor(term.t_nrow, 0); + sprintf( mbuf, "[%10u]", envram) ; + char *sp = mbuf ; + while( *sp) + TTputc( *sp++) ; + + TTmove( term.t_nrow, 0) ; + movecursor( term.t_nrow, 0) ; } #endif #endif @@ -442,42 +419,36 @@ static void dspram( void) #if CLEAN -/* - * cexit() +/* cexit() * * int status; return status of emacs */ void cexit( int status) { - struct buffer *bp; /* buffer list pointer */ - struct window *wp; /* window list pointer */ - struct window *tp; /* temporary window pointer */ - - /* first clean up the windows */ - wp = wheadp; - while (wp) { - tp = wp->w_wndp; - free(wp); - wp = tp; +/* first clean up the windows */ + window_p wp = wheadp ; + while( wp) { + window_p tp = wp->w_wndp ; + free( wp) ; + wp = tp ; } - wheadp = NULL; + + wheadp = NULL ; - /* then the buffers */ - bp = bheadp; - while (bp) { - bp->b_nwnd = 0; - bp->b_flag = 0; /* don't say anything about a changed buffer! */ - zotbuf(bp); - bp = bheadp; +/* then the buffers */ + buffer_p bp ; + while( (bp = bheadp) != NULL) { + bp->b_nwnd = 0 ; + bp->b_flag = 0 ; /* don't say anything about a changed buffer! */ + zotbuf( bp) ; } - /* and the kill buffer */ - kdelete(); +/* and the kill buffer */ + kdelete() ; - /* and the video buffers */ - vtfree(); +/* and the video buffers */ + vtfree() ; -#undef exit - exit(status); + (exit)( status) ; /* call the function, not the macro */ } #endif diff --git a/maze.cmd b/maze.cmd index 18b49d7..edea298 100644 --- a/maze.cmd +++ b/maze.cmd @@ -1,6 +1,7 @@ -# record seed +## maze.cmd -- draw a block maze + # 5 set $seed -set %S $seed +set %S $seed # record seed # setup direction offsets set %D1 0 diff --git a/names.c b/names.c index 378d260..c5ea463 100644 --- a/names.c +++ b/names.c @@ -16,6 +16,7 @@ #include "bind.h" #include "bindable.h" #include "buffer.h" +#include "defines.h" /* malloc/allocate */ #include "display.h" #include "eval.h" #include "exec.h" @@ -49,8 +50,8 @@ const name_bind names[] = { {"!case-word-lower", lowerword, META | 'L'} , {"!case-word-upper", upperword, META | 'U'} , {" change-file-name", filename, CTLX | 'N'} , - {" change-screen-size", newsize, META | CTL_ | 'D'} , /* M^S */ - {" change-screen-width", newwidth, META | CTL_ | 'T'} , + {" change-screen-size", (fnp_t) newsize, META | CTL_ | 'D'} , /* M^S */ + {" change-screen-width", (fnp_t) newwidth, META | CTL_ | 'T'} , {" clear-and-redraw", (fnp_t) redraw, CTL_ | 'L'} , {" clear-message-line", (fnp_t) clrmes, 0} , {" copy-region", copyregion, META | 'W'} , @@ -191,7 +192,7 @@ const name_bind names[] = { {" shell-command", spawn, CTLX | '!'} , {" shrink-window", shrinkwind, CTLX | CTL_ | 'Z'} , {" split-current-window", splitwind, CTLX | '2'} , - {" store-macro", storemac, 0} , + {" store-macro", (fnp_t) storemac, 0} , {" store-procedure", storeproc, 0} , #if BSD | SVR4 {" suspend-emacs", bktoshell, CTLX | 'D'} , /* BSD MS */ @@ -201,7 +202,7 @@ const name_bind names[] = { {" unbind-key", unbindkey, META | CTL_ | 'K'} , {" universal-argument", (fnp_t) unarg, CTL_ | 'U'} , {" unmark-buffer", unmark, META | '~'} , - {" update-screen", upscreen, 0} , + {" update-screen", (fnp_t) upscreen, 0} , {" view-file", viewfile, CTLX | CTL_ | 'V'} , {"!wrap-word", wrapword, META | SPEC | 'W'} , /* hook */ {" write-file", filewrite, CTLX | CTL_ | 'W'} , diff --git a/pklock.h b/pklock.h index 745aec5..0a24892 100644 --- a/pklock.h +++ b/pklock.h @@ -2,7 +2,7 @@ #ifndef _PKLOCK_H_ #define _PKLOCK_H_ -#include "estruct.h" +#include "defines.h" /* FILOCK, BSD, SVR4 */ #if (FILOCK && BSD) || SVR4 char *dolock( const char *fname) ; diff --git a/posix.c b/posix.c index 29b1a37..fdf649d 100644 --- a/posix.c +++ b/posix.c @@ -1,18 +1,17 @@ /* posix.c -- posix implementation of termio.h */ -#ifdef POSIX - #include "termio.h" -/* posix.c - * - * 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. - * - * modified by Petri Kutvonen - * - * based on termio.c, with all the old cruft removed, and - * fixed for termios rather than the old termio.. Linus Torvalds +#include "defines.h" /* POSIX */ +#ifdef POSIX + +/* 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. + + modified by Petri Kutvonen + + based on termio.c, with all the old cruft removed, and + fixed for termios rather than the old termio.. Linus Torvalds */ #include @@ -24,21 +23,19 @@ #include #include -#include "estruct.h" #include "retcode.h" #include "utf8.h" -int ttrow = HUGE ; /* Row location of HW cursor */ -int ttcol = HUGE ; /* Column location of HW cursor */ +int ttrow = -1 ; /* Row location of HW cursor */ +int ttcol = -1 ; /* Column location of HW cursor */ -/* Since Mac OS X's termios.h doesn't have the following 2 macros, define them. - */ -#if BSD || defined(SYSV) && (defined(_DARWIN_C_SOURCE) || defined(_FREEBSD_C_SOURCE)) +/* Define missing macroes for BSD and CYGWIN environment */ +#if BSD #define OLCUC 0000002 #define XCASE 0000004 #endif -#ifdef CYGWIN +#ifdef __CYGWIN__ /* gcc predefined (see cpp -dM) */ #define XCASE 0 #define ECHOPRT 0 #define PENDIN 0 @@ -96,10 +93,8 @@ void ttopen(void) kbdflgs = fcntl(0, F_GETFL, 0); kbdpoll = FALSE; - /* on all screens we are not sure of the initial position - of the cursor */ - ttrow = 999; - ttcol = 999; +/* on all screens we are not sure of the initial position of the cursor */ + ttrow = ttcol = -1 ; } /* @@ -154,27 +149,28 @@ void ttflush(void) exit(15); } -/* - * Read a character from the terminal, performing no editing and doing no echo - * at all. - * Very simple on CPM, because the system can do exactly what you want. - */ -int ttgetc(void) -{ - static char buffer[32]; - static int pending; - unicode_t c; - int count, bytes = 1, expected; - count = pending; - if (!count) { - count = read(0, buffer, sizeof(buffer)); - if (count <= 0) - return 0; - pending = count; +/* Read a character from the terminal, performing no editing and doing no + echo at all. + */ +int ttgetc( void) { + static char buffer[ 32] ; + static int pending ; + unicode_t c ; + + int count = pending ; + if( !count) { + count = read( 0, buffer, sizeof( buffer)) ; + if( count <= 0) + return 0 ; + + pending = count ; } - c = (unsigned char) buffer[0]; + int bytes = 1 ; + c = (unsigned char) buffer[ 0] ; +#if 0 // temporary fix for wsl + if (c >= 32 && c < 128) goto done; @@ -191,7 +187,7 @@ int ttgetc(void) * delay for some *very* unusual utf8 character * input. */ - expected = 2; + int expected = 2; if ((c & 0xe0) == 0xe0) expected = 6; @@ -225,9 +221,10 @@ int ttgetc(void) bytes = utf8_to_unicode(buffer, 0, pending, &c); done: - pending -= bytes; - memmove(buffer, buffer+bytes, pending); - return c; +#endif + pending -= bytes ; + memmove( buffer, buffer + bytes, pending) ; + return c ; } /* typahead: Check to see if any characters are already in the @@ -247,8 +244,6 @@ int typahead(void) return x; } -#else -typedef void _pedantic_empty_translation_unit ; -#endif /* not POSIX */ +#endif /* end of posix.c */ diff --git a/random.c b/random.c index 4f2f3be..28ddfc3 100644 --- a/random.c +++ b/random.c @@ -14,8 +14,8 @@ #include "basic.h" #include "buffer.h" +#include "defines.h" #include "display.h" -#include "estruct.h" #include "execute.h" #include "input.h" #include "line.h" @@ -219,30 +219,31 @@ boolean setccol( int pos) { */ BBINDABLE( twiddle) { unicode_t c ; - boolean eof_f = FALSE ; assert( !(curbp->b_mode & MDVIEW)) ; int len = llength( curwp->w_dotp) ; - if( len < 2 || curwp->w_doto == 0) /* at least 2 chars & not bol */ + if( len < 2 || curwp->w_doto == 0) /* at least 2 bytes & not bol */ return FALSE ; - if( curwp->w_doto == len) { /* at end of line */ + if( curwp->w_doto == len) { /* at end of line */ backchar( FALSE, 1) ; - eof_f = TRUE ; + if( curwp->w_doto == 0) { + /* only one combined character on this line */ + forwchar( FALSE, 1) ; + return FALSE ; + } } - len = lgetchar( &c) ; /* len => unicode or extended ASCII */ - ldelchar( 1, FALSE) ; backchar( FALSE, 1) ; + len = lgetchar( &c) ; /* len => unicode or extended ASCII */ + ldelchar( 1, FALSE) ; + forwchar( FALSE, 1) ; if( len == 1) linsert_byte( 1, c) ; else linsert( 1, c) ; - if( eof_f == TRUE) - forwchar( FALSE, 1) ; - lchange( WFEDIT) ; return TRUE ; } @@ -836,7 +837,7 @@ static int adjustmode( int kind, int global) { } -static int iovstring( int f, int n, const char *prompt, int (*fun)( char *)) { +static int iovstring( int f, int n, const char *prompt, boolean (*fun)( char *)) { char *tstring ; /* string to add */ /* ask for string to insert */ diff --git a/region.c b/region.c index c31a431..6f849e1 100644 --- a/region.c +++ b/region.c @@ -12,7 +12,7 @@ #include #include "buffer.h" -#include "estruct.h" +#include "defines.h" #include "line.h" #include "mlout.h" #include "random.h" diff --git a/search.c b/search.c index 7f6d4fd..c186a40 100644 --- a/search.c +++ b/search.c @@ -65,8 +65,8 @@ #include "basic.h" #include "buffer.h" +#include "defines.h" #include "display.h" -#include "estruct.h" #include "input.h" #include "isa.h" #include "line.h" diff --git a/sharpmaz.cmd b/sharpmaz.cmd new file mode 100644 index 0000000..5d0b974 --- /dev/null +++ b/sharpmaz.cmd @@ -0,0 +1,54 @@ +## sharpmaz.cmd -- redraw a block maze using line characters + +execute-file maze.cmd + +set %meml $curline +set %memc $curcol +end-of-line +set %ec &sub $curcol 1 +end-of-file +set %el &sub $curline 1 +previous-line +set %spaces $line +beginning-of-file +set %old $line +set $line %spaces +next-line + +!while &less $curline %el + set $curcol 1 + !while &less $curcol %ec + !if ¬ &equ $curchar 32 + set %v 0 + set %inc 1 + previous-line + !gosub check + next-line + backward-character + !gosub check + 2 forward-character + !gosub check + next-line + backward-character + !gosub check + previous-line + # alternatively use single width "╳╵╴┘╶└─┴╷│┐┤┌├┬┼" + set $curchar &asc &mid "╳╹╸┛╺┗━┻╻┃┓┫┏┣┳╋" &add %v 1 1 + !endif + forward-character + !endwhile + next-line +!endwhile + +beginning-of-file +set $line %old +set $curline %meml +set $curcol %memc +!return + +:check + !if ¬ &equ $curchar 32 + set %v &add %v %inc + !endif + set %inc &tim %inc 2 +!return diff --git a/spawn.c b/spawn.c index f48e74a..d7a3e2f 100644 --- a/spawn.c +++ b/spawn.c @@ -12,11 +12,9 @@ #include #include -#include "defines.h" - #include "buffer.h" +#include "defines.h" #include "display.h" -#include "estruct.h" #include "exec.h" #include "file.h" #include "flook.h" @@ -27,8 +25,6 @@ #if USG | BSD #include -#ifdef SIGWINCH -#endif #endif @@ -173,97 +169,88 @@ BINDABLE( execprg) { /* Pipe a one line command into a window - * Bound to ^X @ + * Bound to pipe-command ^X @ */ BINDABLE( pipecmd) { - int s ; /* return status from CLI */ - struct window *wp ; /* pointer to new window */ - buffer_p bp ; /* pointer to buffer to zot */ + window_p wp ; /* pointer to new window */ char *mlarg ; - char *line ; /* command line send to shell */ - static char bname[] = "command" ; - static char filnam[ NSTRING] = "command" ; + const char filnam[] = "command" ; - /* don't allow this command if restricted */ +/* don't allow this command if restricted */ if( restflag) return resterr() ; - /* get the command to pipe in */ - s = newmlarg( &mlarg, "@", 0) ; +/* get the command to pipe in */ + int s = newmlarg( &mlarg, "pipe-command: ", 0) ; if( s != TRUE) return s ; - line = malloc( strlen( mlarg) + strlen( filnam) + 2) ; - if( line == NULL) { + char *cmdline = malloc( strlen( mlarg) + strlen( filnam) + 4) ; + if( cmdline == NULL) { free( mlarg) ; return FALSE ; } - strcpy( line, mlarg) ; + strcpy( cmdline, mlarg) ; free( mlarg) ; + strcat( cmdline, " > ") ; + strcat( cmdline, filnam) ; - /* get rid of the command output buffer if it exists */ - if ((bp = bfind(bname, FALSE, 0)) != FALSE) { - /* try to make sure we are off screen */ - wp = wheadp; - while (wp != NULL) { - if (wp->w_bufp == bp) { +/* get rid of the command output buffer if it exists */ + buffer_p bp = bfind( filnam, FALSE, 0) ; + if( bp != NULL) { + /* try to make sure we are off screen */ + for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) { + if( wp->w_bufp == bp) { #if PKCODE - if (wp == curwp) - delwind(FALSE, 1); + if( wp == curwp) + delwind( FALSE, 1) ; else - onlywind(FALSE, 1); - break; + onlywind( FALSE, 1) ; + break ; #else - onlywind(FALSE, 1); - break; + onlywind( FALSE, 1) ; + break ; #endif } - wp = wp->w_wndp; } if( zotbuf( bp) != TRUE) { - free( line) ; + free( cmdline) ; return FALSE ; } } + #if USG | BSD TTflush(); TTclose(); /* stty to old modes */ TTkclose(); - strcat( line, ">") ; - strcat( line, filnam) ; - ue_system( line) ; - free( line) ; + ue_system( cmdline) ; + free( cmdline) ; TTopen(); TTkopen(); TTflush(); sgarbf = TRUE; s = TRUE; #else - if (s != TRUE) + if( s != TRUE) return s; #endif - /* split the current window to make room for the command output */ - if (splitwind(FALSE, 1) == FALSE) - return FALSE; +/* split the current window to make room for the command output +** and read the stuff in */ + if( splitwind( FALSE, 1) == FALSE + || getfile( filnam, FALSE) == FALSE) + return FALSE ; - /* and read the stuff in */ - if (getfile(filnam, FALSE) == FALSE) - return FALSE; +/* make this window in VIEW mode, update all mode lines */ + curwp->w_bufp->b_mode |= MDVIEW ; + for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) + wp->w_flag |= WFMODE ; - /* make this window in VIEW mode, update all mode lines */ - curwp->w_bufp->b_mode |= MDVIEW; - wp = wheadp; - while (wp != NULL) { - wp->w_flag |= WFMODE; - wp = wp->w_wndp; - } - - /* and get rid of the temporary file */ - unlink(filnam); - return TRUE; +/* and get rid of the temporary file */ + unlink( filnam) ; + return TRUE ; } diff --git a/tcap.c b/tcap.c index 5ae6cee..53f829e 100644 --- a/tcap.c +++ b/tcap.c @@ -20,8 +20,8 @@ #include #include +#include "defines.h" #include "display.h" -#include "estruct.h" #include "termio.h" #if TERMCAP @@ -83,7 +83,7 @@ static char *_UP, _PC, *CM, *CE, *CL, *SO, *SE; static char *CS, *DL, *AL, *SF, *SR; # endif -struct terminal term = { +terminal_t term = { 480, /* actual 479 on 2560x1440 landscape terminal window */ 2550, /* actual 2541 */ 0, /* These four values are set dynamically at open time. */ @@ -231,16 +231,14 @@ static void tcapclose(void) } # endif -static void tcapkopen(void) -{ +static void tcapkopen( void) { # if PKCODE - putpad(TI); - ttflush(); - ttrow = 999; - ttcol = 999; - sgarbf = TRUE; + putpad( TI) ; + ttflush() ; + ttrow = ttcol = -1 ; + sgarbf = TRUE ; # endif - strcpy(sres, "NORMAL"); + strcpy(sres, "NORMAL") ; } static void tcapkclose(void) diff --git a/terminal.h b/terminal.h index 3f7d375..247c7dd 100644 --- a/terminal.h +++ b/terminal.h @@ -6,45 +6,45 @@ #include "retcode.h" #include "utf8.h" -/* The editor communicates with the display using a high level interface. A - * "TERM" structure holds useful variables, and indirect pointers to routines - * that do useful operations. The low level get and put routines are here too. - * This lets a terminal, in addition to having non standard commands, have - * funny get and put character code too. The calls might get changed to - * "termp->t_field" style in the future, to make it possible to run more than - * one terminal type. +/* The editor communicates with the display using a high level interface. + A "TERM" structure holds useful variables, and indirect pointers to + routines that do useful operations. The low level get and put routines + are here too. This lets a terminal, in addition to having non standard + commands, have funny get and put character code too. The calls might + get changed to "termp->t_field" style in the future, to make it possible + to run more than one terminal type. */ -struct terminal { - const short t_maxrow ; /* max number of rows allowable */ - const short t_maxcol ; /* max number of columns allowable */ - short t_mrow ; /* max number of rows displayable */ - short t_nrow ; /* current number of rows displayed */ - short t_mcol ; /* max number of rows displayable */ - short t_ncol ; /* current number of columns displayed */ - short t_margin; /* min margin for extended lines */ - short t_scrsiz; /* size of scroll region " */ - int t_pause; /* # times thru update to pause */ - void (*t_open)(void); /* Open terminal at the start. */ - void (*t_close)(void); /* Close terminal at end. */ - void (*t_kopen)(void); /* Open keyboard */ - void (*t_kclose)(void); /* close keyboard */ - int (*t_getchar)(void); /* Get character from keyboard. */ - int (*t_putchar)( unicode_t) ; /* Put character to display. */ - void (*t_flush) (void); /* Flush output buffers. */ - void (*t_move)(int, int);/* Move the cursor, origin 0. */ - void (*t_eeol)(void); /* Erase to end of line. */ - void (*t_eeop)(void); /* Erase to end of page. */ - void (*t_beep)(void); /* Beep. */ - void (*t_rev)(int); /* set reverse video state */ - int (*t_rez)(char *); /* change screen resolution */ +typedef struct { + const short t_maxrow ; /* max number of rows allowable */ + const short t_maxcol ; /* max number of columns allowable */ + short t_mrow ; /* max number of rows displayable */ + short t_nrow ; /* current number of rows displayed */ + short t_mcol ; /* max number of rows displayable */ + short t_ncol ; /* current number of columns displayed */ + short t_margin ; /* min margin for extended lines */ + short t_scrsiz ; /* size of scroll region */ + int t_pause ; /* # times thru update to pause */ + void (*t_open)( void) ; /* Open terminal at the start */ + void (*t_close)( void) ; /* Close terminal at end. */ + void (*t_kopen)( void) ; /* Open keyboard */ + void (*t_kclose)( void) ; /* close keyboard */ + int (*t_getchar)( void) ; /* Get character from keyboard */ + int (*t_putchar)( unicode_t) ; /* Put character to display */ + void (*t_flush) (void) ; /* Flush output buffers */ + void (*t_move)( int, int) ; /* Move the cursor, origin 0 */ + void (*t_eeol)( void) ; /* Erase to end of line */ + void (*t_eeop)( void) ; /* Erase to end of page */ + void (*t_beep)( void) ; /* Beep */ + void (*t_rev)( int) ; /* set reverse video state */ + int (*t_rez)( char *) ; /* change screen resolution */ #if COLOR - int (*t_setfor) (); /* set forground color */ - int (*t_setback) (); /* set background color */ + int (*t_setfor)() ; /* set forground color */ + int (*t_setback)() ; /* set background color */ #endif -#if SCROLLCODE - void (*t_scroll)(int, int,int); /* scroll a region of the screen */ +#if SCROLLCODE + void (*t_scroll)( int, int,int) ; /* scroll a region of the screen */ #endif -}; +} terminal_t ; /* TEMPORARY macros for terminal I/O (to be placed in a machine dependant place later) @@ -68,11 +68,8 @@ struct terminal { #define TTbacg (*term.t_setback) #endif -/* Terminal table defined only in term.c */ -extern struct terminal term ; - -extern int ttrow ; /* Row location of HW cursor */ -extern int ttcol ; /* Column location of HW cursor */ +/* Terminal table defined only in tcap.c */ +extern terminal_t term ; extern boolean eolexist ; /* does clear to EOL exist? */ extern boolean revexist ; /* does reverse video exist? */ diff --git a/termio.c b/termio.c index f17265e..3ed67b0 100644 --- a/termio.c +++ b/termio.c @@ -1,21 +1,19 @@ /* termio.c -- implements termio.h */ -#if !defined( POSIX) - #include "termio.h" -/* TERMIO.C - * - * 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. - * - * modified by Petri Kutvonen +#include "defines.h" /* POSIX */ +#ifndef POSIX + +/* 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. + + modified by Petri Kutvonen */ #include #include -#include "estruct.h" #include "retcode.h" #include "utf8.h" @@ -23,8 +21,8 @@ #include #include -int ttrow = HUGE ; /* Row location of HW cursor */ -int ttcol = HUGE ; /* Column location of HW cursor */ +int ttrow = -1 ; /* Row location of HW cursor */ +int ttcol = -1 ; /* Column location of HW cursor */ #if USG /* System V */ @@ -141,8 +139,7 @@ void ttopen(void) /* on all screens we are not sure of the initial position of the cursor */ - ttrow = 999; - ttcol = 999; + ttrow = ttcol = -1 ; } /* @@ -258,14 +255,12 @@ int typahead( void) return kbdqp; #endif -#if !UNIX +# if !UNIX return FALSE; -#endif +# endif } -#endif +# endif -#else -typedef void _pedantic_empty_translation_unit ; #endif /* not POSIX */ /* end of termio.c */ diff --git a/termio.h b/termio.h index b2603c2..d98a450 100644 --- a/termio.h +++ b/termio.h @@ -6,8 +6,6 @@ #define TYPEAH 1 /* type ahead causes update to be skipped */ -#define HUGE 1000 /* Huge number (for row/col) */ - extern int ttrow ; /* Row location of HW cursor */ extern int ttcol ; /* Column location of HW cursor */ diff --git a/ue.rc b/ue.rc deleted file mode 100644 index fc43f32..0000000 --- a/ue.rc +++ /dev/null @@ -1,163 +0,0 @@ -# UE.RC -# -# Startup file for µEMACS 4.2 -# This file is executed every time the editor is entered. -# If you want to keep compatibility with em (uEmacs/PK) or me (MicroEMACS) -# cp emacs.rc ~/.emacsrc -# cp ue.rc ~/.uerc -# otherwise -# cp ue.rc ~/.emacsrc - -set $discmd "FALSE" -set $tab 4 - -; Help facility - -40 store-macro - set $discmd "FALSE" - !if ¬ &seq $cbufname "emacs.hlp" - write-message "(Loading Help)" - !force help - !if ¬ &seq $cbufname "emacs.hlp" - write-message "(Failed to load Help)" - !else - !force 8 resize-window - bind-to-key execute-macro-39 FN5 - bind-to-key execute-macro-38 FN6 - bind-to-key execute-macro-37 FNH - bind-to-key execute-macro-36 FNF - beginning-of-line - 2 forward-character - 1 redraw-display - set %hlpupdn "[PgUp] / [PgDn]" - set %hlphelp "[F1]" - run helponhelp - !endif - !else - set %hlpcode &lef $line 2 - !if &seq %hlpcode ".." - set %hlptopic &mid $line 4 99 - end-of-line - !force search-forward %hlptopic - beginning-of-line - 2 forward-character - 1 redraw-display - run helponhelp - !else - !force search-reverse "=>" - bind-to-key previous-page FN5 - bind-to-key next-page FN6 - bind-to-key beginning-of-file FNH - bind-to-key end-of-file FNF - !force delete-window - clear-message-line - !endif - !endif - set $discmd "TRUE" -!endm - -bind-to-key execute-macro-40 M-? -bind-to-key execute-macro-40 FNP -bind-to-key beginning-of-file FNH -bind-to-key end-of-file FNF - -; Help on Help - -store-procedure helponhelp - !if &seq &rig $line 5 "INDEX" - write-message &cat "Select topic from list and press " %hlphelp - !else - write-message &cat "Use " &cat %hlpupdn &cat " to scan help file -- " &cat %hlphelp " to toggle help window" - !endif -!endm - -; Previous help page - -39 store-macro - !if &seq $cbufname "emacs.hlp" - beginning-of-line - !force search-reverse "=>" - 2 forward-character - 1 redraw-display - run helponhelp - !else - previous-page - !endif -!endm - -; Next help page - -38 store-macro - !if &seq $cbufname "emacs.hlp" - beginning-of-line - 2 forward-character - !force search-forward "=>" - 1 redraw-display - run helponhelp - !else - next-page - !endif -!endm - -37 store-macro - beginning-of-file - !if &seq $cbufname "emacs.hlp" - execute-macro-39 - !endif -!endm - -36 store-macro - end-of-file - !if &seq $cbufname "emacs.hlp" - execute-macro-39 - !endif -!endm - -; Set up auto CMODE - -35 store-macro - !if &seq &mid $cfname 1 7 "/tmp/Re" - add-mode "wrap" - !return - !endif - !if &gre &sin $cfname "/.ed" 0 - add-mode "wrap" - !return - !endif - !if &gre &sin $cfname "/.let" 0 - add-mode "wrap" - !return - !endif - !if &gre &sin $cfname "/.art" 0 - add-mode "wrap" - !return - !endif - !if &gre &sin $cfname "/nn." 0 - add-mode "wrap" - !return - !endif - set %rctmp &sin $cfname "." - !if &equ %rctmp 0 - !return - !endif - set %rctmp &mid $cfname &add %rctmp 1 5 - !if &or &seq %rctmp "c" &seq %rctmp "h" - add-mode "cmode" - !endif - !if &or &seq %rctmp "txt" &or &seq %rctmp "doc" &or &seq %rctmp "tmp" &seq %rctmp "tex" - add-mode "wrap" - !endif - -!endm - -bind-to-key execute-macro-35 M-FNR - -; Make cut-paste easier in window systems - -bind-to-key newline ^J - -!if &or &gre &sin $LANG "UTF-8" 0 &gre &sin $LANG "utf8" 0 - add-global-mode "utf-8" -!endif - -set $discmd "TRUE" diff --git a/utf8.c b/utf8.c index 10cf20c..d7cfcd7 100644 --- a/utf8.c +++ b/utf8.c @@ -1,27 +1,23 @@ -/* utf8.c -- implements utf8.h, converts between unicode and UTF-8 */ - -#define _XOPEN_SOURCE /* wcwidth in wchar.h */ - +/* utf8.c -- implements utf8.h, conversion between unicode and UTF-8 */ #include "utf8.h" #include -#include +#include /* either _XOPEN_SOURCE or _GNU_SOURCE */ /* Display width of UTF-8 character */ int _utf8_width( unicode_t c) { -#if CYGWIN - assert( sizeof( wchar_t) == 2) ; /* wcwidth only supports UTF-16 */ - return (c < 0x10000) ? wcwidth( (wchar_t) c) : -1 ; +#if __SIZEOF_WCHAR_T__ == 2 /* wcwidth only supports UTF-16 */ + return (c < 0x10000) ? wcwidth( (wchar_t) c) : -1 ; #else - return wcwidth( (wchar_t) c) ; + return wcwidth( (wchar_t) c) ; #endif } int utf8_width( unicode_t c) { - int w = _utf8_width( c) ; - return (w < 0) ? 2 : w ; /* display \u if can't figure out width */ + int w = _utf8_width( c) ; + return (w < 0) ? 2 : w ; /* display \u if can't figure out width */ } @@ -38,55 +34,49 @@ int utf8_width( unicode_t c) { * are happily accepted and decoded, as are the various "invalid values". */ unsigned utf8_to_unicode( const char *line, unsigned index, unsigned len, - unicode_t *res) { - unicode_t value ; - unsigned c ; - unsigned bytes, mask, i; + unicode_t *res) { + assert( index < len) ; + unsigned c = *res = (unsigned char) line[ index] ; - if( index >= len) - return 0 ; - - *res = c = line[ index] & 0xFFU ; - - /* - * 0xxxxxxx is valid one byte utf8 + /* 0xxxxxxx is valid one byte utf8 * 10xxxxxx is invalid UTF-8 start byte, we assume it is Latin1 * 1100000x is start of overlong encoding sequence * Sequence longer than 4 bytes are invalid * Last valid code is 0x10FFFF, encoding start with 0xF4 */ if( c <= 0xC1 || c > 0xF4) - return 1; + return 1 ; /* Ok, it's 11xxxxxx, do a stupid decode */ - mask = 0x20; - bytes = 2; + unsigned mask = 0x20 ; + unsigned bytes = 2 ; while( (c & mask) != 0) { - bytes++; - mask >>= 1; + bytes++ ; + mask >>= 1 ; } - /* bytes is in range [2..4] as c was in range [C2..F4] */ - len -= index; - if (bytes > len) - return 1; + /* bytes is in range [2..4] as c was in range [C2..F4] */ + len -= index ; + if( bytes > len) + return 1 ; - value = c & (mask-1); + unicode_t value = c & (mask - 1) ; /* Ok, do the bytes */ - line += index; - for (i = 1; i < bytes; i++) { - c = line[i] & 0xFFU ; - if ((c & 0xc0) != 0x80) - return 1; - value = (value << 6) | (c & 0x3f); + line += index ; + for( unsigned i = 2 ; i <= bytes ; i++) { + c = (unsigned char) *++line ; + if( (c & 0xc0) != 0x80) + return 1 ; + + value = (value << 6) | (c & 0x3f) ; } if( value > 0x10FFFF) /* Avoid 110000 - 13FFFF */ return 1 ; - *res = value; - return bytes; + *res = value ; + return bytes ; } @@ -106,12 +96,12 @@ unsigned unicode_to_utf8( unicode_t c, char *utf8) { assert( c <= 0x10FFFF) ; #ifdef NDEBUG - if( c > 0x10FFFF) /* Let's assume this is due to sign extension */ - c &= 0xFF ; + if( c > 0x10FFFF) /* Let's assume this is due to sign extension */ + c &= 0xFF ; #endif if( c <= 0x7f) - *utf8 = (char) c ; + *utf8 = (char) c ; else { unsigned prefix = 0x40 ; char *p = utf8 ; @@ -122,38 +112,38 @@ unsigned unicode_to_utf8( unicode_t c, char *utf8) { c >>= 6 ; } while( c >= prefix) ; - *p-- = *utf8 ; - *utf8++ = (char) (c - 2 * prefix) ; - if( utf8 < p) { /* swap middle two bytes if 4 bytes utf-8 code */ - char c = *p ; - *p = *utf8 ; - *utf8 = c ; - } + *p-- = *utf8 ; + *utf8++ = (char) (c - 2 * prefix) ; + if( utf8 < p) { /* swap middle two bytes if 4 bytes utf-8 code */ + char c = *p ; + *p = *utf8 ; + *utf8 = c ; + } } return bytes ; } unsigned utf8_revdelta( unsigned char *p, unsigned pos) { - unsigned delta = 0 ; + unsigned delta = 0 ; - if( (*p & 0xC0) == 0x80) { - unsigned char c ; + if( (*p & 0xC0) == 0x80) { + unsigned char c ; - c = *--p ; - if( (c & 0xE0) == 0xC0) /* valid 2 bytes unicode seq */ - delta = 1 ; - else if( ((c & 0xC0) == 0x80) && (pos > 1)) { - c = *--p ; - if( (c & 0xF0) == 0xE0) /* valid 3 bytes unicode seq */ - delta = 2 ; - else if( ((c & 0xC0) == 0x80) && (pos > 2)) - if( (p[ -1] & 0xF8) == 0xF0) /* valid 4 bytes unicode seq */ - delta = 3 ; - } - } + c = *--p ; + if( (c & 0xE0) == 0xC0) /* valid 2 bytes unicode seq */ + delta = 1 ; + else if( ((c & 0xC0) == 0x80) && (pos > 1)) { + c = *--p ; + if( (c & 0xF0) == 0xE0) /* valid 3 bytes unicode seq */ + delta = 2 ; + else if( ((c & 0xC0) == 0x80) && (pos > 2)) + if( (p[ -1] & 0xF8) == 0xF0) /* valid 4 bytes unicode seq */ + delta = 3 ; + } + } - return delta ; + return delta ; } diff --git a/utf8.h b/utf8.h index 4939459..24a8d1f 100644 --- a/utf8.h +++ b/utf8.h @@ -1,4 +1,4 @@ -/* utf8.h -- */ +/* utf8.h -- conversion between unicode and UTF-8 */ #ifndef _UTF8_H_ #define _UTF8_H_ diff --git a/window.c b/window.c index d5448fa..b3e87d9 100644 --- a/window.c +++ b/window.c @@ -6,11 +6,12 @@ */ #include +#include /* malloc(), free() */ #include "basic.h" #include "buffer.h" +#include "defines.h" #include "display.h" /* upmode() */ -#include "estruct.h" #include "execute.h" #include "line.h" #include "mlout.h" @@ -52,7 +53,7 @@ TBINDABLE( redraw) { /* The command make the next window (next => down the screen) the current window. There are no real errors, although the command does nothing if - there is only 1 window on the screen. Bound to "C-X C-N". + there is only 1 window on the screen. Bound to "C-X O". with an argument this command finds the th window from the top @@ -318,7 +319,10 @@ BINDABLE( splitwind) { return FALSE ; } - wp = xmalloc( sizeof *wp) ; + wp = malloc( sizeof *wp) ; + if( wp == NULL) + return mloutfail( "Out of memory") ; + ++curbp->b_nwnd; /* Displayed twice. */ wp->w_bufp = curbp; wp->w_dotp = curwp->w_dotp; @@ -557,89 +561,84 @@ BINDABLE( restwnd) { } +static void adjust( window_p wp, int screenrows) { + wp->w_ntrows = screenrows - wp->w_toprow - 2 ; + wp->w_flag |= WFHARD | WFMODE ; +} + /* resize the screen, re-writing the screen * * int f; default flag * int n; numeric argument */ -BINDABLE( newsize) { - window_p wp; /* current window being examined */ - window_p nextwp; /* next window to scan */ - window_p lastwp; /* last window scanned */ - int lastline; /* screen line of last line of current window */ +BBINDABLE( newsize) { + window_p wp ; /* current window being examined */ /* if the command defaults, assume the largest */ - if (f == FALSE) + if( f == FALSE) n = term.t_mrow ; /* make sure it's in range */ - if( n < 3 || n > term.t_mrow) + if( n < MINROWS || n > term.t_mrow) return mloutfail( "%%Screen size out of range") ; - if (term.t_nrow == n - 1) - return TRUE; - else if (term.t_nrow < n - 1) { - + if( term.t_nrow == n - 1) + /* no change */ + return TRUE ; + else if( term.t_nrow < n - 1) { + /* new size is bigger */ /* go to the last window */ - wp = wheadp; - while (wp->w_wndp != NULL) - wp = wp->w_wndp; + for( wp = wheadp ; wp->w_wndp != NULL ; wp = wp->w_wndp) + ; /* and enlarge it as needed */ - wp->w_ntrows = n - wp->w_toprow - 2; - wp->w_flag |= WFHARD | WFMODE; - + adjust( wp, n) ; } else { - + /* new size is smaller */ /* rebuild the window structure */ assert( wheadp->w_toprow == 0) ; /* proves coverity wrong */ - nextwp = wheadp; - wp = NULL; - lastwp = NULL; - while (nextwp != NULL) { - wp = nextwp; - nextwp = wp->w_wndp; + window_p lastwp = NULL ; + for( window_p nextwp = wheadp ; nextwp != NULL ; ) { + wp = nextwp ; + nextwp = wp->w_wndp ; + + /* expand previous window if current would have zero lines */ + if( wp->w_toprow == n - 2) + adjust( lastwp, n) ; /* get rid of it if it is too low */ - if (wp->w_toprow > n - 2) { - + if( wp->w_toprow >= n - 2) { /* save the point/mark if needed */ - if (--wp->w_bufp->b_nwnd == 0) { - wp->w_bufp->b_dotp = wp->w_dotp; - wp->w_bufp->b_doto = wp->w_doto; - wp->w_bufp->b_markp = wp->w_markp; - wp->w_bufp->b_marko = wp->w_marko; + if( --wp->w_bufp->b_nwnd == 0) { + wp->w_bufp->b_dotp = wp->w_dotp ; + wp->w_bufp->b_doto = wp->w_doto ; + wp->w_bufp->b_markp = wp->w_markp ; + wp->w_bufp->b_marko = wp->w_marko ; } /* update curwp and lastwp if needed */ - if (wp == curwp) - curwp = wheadp; - curbp = curwp->w_bufp; - if (lastwp != NULL) - lastwp->w_wndp = NULL; + if( wp == curwp) { + curwp = wheadp ; + curbp = curwp->w_bufp ; + } /* free the structure */ - free((char *) wp); - wp = NULL; - + free( wp) ; + lastwp->w_wndp = NULL ; } else { - /* need to change this window size? */ - lastline = wp->w_toprow + wp->w_ntrows - 1; - if (lastline >= n - 2) { - wp->w_ntrows = - n - wp->w_toprow - 2; - wp->w_flag |= WFHARD | WFMODE; - } - } + /* need to change this window size? */ + if( (wp->w_toprow + wp->w_ntrows - 1) >= n - 2) + adjust( wp, n) ; - lastwp = wp; + lastwp = wp ; + } } } /* screen is garbage */ - term.t_nrow = n - 1; - sgarbf = TRUE; - return TRUE; + term.t_nrow = n - 1 ; + sgarbf = TRUE ; + return TRUE ; } @@ -648,31 +647,25 @@ BINDABLE( newsize) { * int f; default flag * int n; numeric argument */ -BINDABLE( newwidth) { - window_p wp; - +BBINDABLE( newwidth) { /* if the command defaults, assume the largest */ - if (f == FALSE) - n = term.t_mcol; + if( f == FALSE) + n = term.t_mcol ; /* make sure it's in range */ - if (n < 10 || n > term.t_mcol) + if( n < MINCOLS || n > term.t_mcol) return mloutfail( "%%Screen width out of range") ; /* otherwise, just re-width it (no big deal) */ - term.t_ncol = n; - term.t_margin = n / 10; - term.t_scrsiz = n - (term.t_margin * 2); + term.t_ncol = n ; + updmargin() ; - /* florce all windows to redraw */ - wp = wheadp; - while (wp) { - wp->w_flag |= WFHARD | WFMOVE | WFMODE; - wp = wp->w_wndp; - } - sgarbf = TRUE; + /* force all windows to redraw */ + for( window_p wp = wheadp ; wp; wp = wp->w_wndp) + wp->w_flag |= WFHARD | WFMOVE | WFMODE ; - return TRUE; + sgarbf = TRUE ; + return TRUE ; } int getwpos(void) diff --git a/window.h b/window.h index a139562..a1e41b4 100644 --- a/window.h +++ b/window.h @@ -55,8 +55,8 @@ extern window_p wheadp ; /* Head of list of windows */ BINDABLE( enlargewind) ; BINDABLE( mvdnwind) ; BINDABLE( mvupwind) ; - BINDABLE( newsize) ; - BINDABLE( newwidth) ; +BBINDABLE( newsize) ; +BBINDABLE( newwidth) ; BINDABLE( nextwind) ; BINDABLE( onlywind) ; BINDABLE( prevwind) ; diff --git a/word.c b/word.c index 7b859f8..8893e5d 100644 --- a/word.c +++ b/word.c @@ -14,7 +14,7 @@ #include "basic.h" #include "buffer.h" -#include "estruct.h" +#include "defines.h" #include "isa.h" #include "line.h" #include "mlout.h" diff --git a/wrapper.c b/wrapper.c index 21dda69..ebb4d3a 100644 --- a/wrapper.c +++ b/wrapper.c @@ -1,5 +1,4 @@ /* wrapper.c -- implements wrapper.h */ - #include "wrapper.h" #include @@ -26,12 +25,4 @@ void xmkstemp( char *template) { close( fd) ; } -void *xmalloc( size_t size) { - void *ret = malloc( size) ; - if( !ret) - die( "Out of memory") ; - - return ret ; -} - /* end of wrapper.c */ diff --git a/wrapper.h b/wrapper.h index 0f556b2..7be2c0e 100644 --- a/wrapper.h +++ b/wrapper.h @@ -2,11 +2,7 @@ #ifndef WRAPPER_H_ #define WRAPPER_H_ -#include /* size_t */ - void xmkstemp( char *fname_template) ; -void *xmalloc( size_t size) ; - #endif /* end of wrapper.h */