Compare commits

...

37 Commits

Author SHA1 Message Date
Renaud 2befa53c3a Merge branch 'unicode' 2021-09-18 09:12:27 +08:00
Renaud 4704d6a352 Remove coverity badge (build is stuck in queue limbo).
Update Unicode support status.
2021-09-16 10:02:09 +08:00
Renaud 2e69f9410f Fix position of cursor to avoid extended display of line. 2021-09-16 09:46:02 +08:00
Renaud 8726e5b8aa Clean up startup and help files. 2021-09-16 09:44:59 +08:00
Renaud 0c584e5490 Revise window flagging on line change.
Evaluation of Value of kill buffer and current line.
2021-09-15 13:15:31 +08:00
Renaud b244adf23a Revise fence handling in CMODE. 2021-09-15 11:55:23 +08:00
Renaud 860bace701 Revise pipe-command. 2021-09-15 11:51:12 +08:00
Renaud 991283b912 Make sure directive keywords are followed by EOS, comment or space separator. 2021-09-13 12:33:32 +08:00
Renaud eff9b64f1d Always refresh window on execution if buffer is displayed, not only on errors.
Insure dot is correct on final !return.
2021-09-12 09:34:28 +08:00
Renaud 8555d07437 Revise command line parsing: making sure something; is token something followed by ; (a comment). 2021-09-11 12:38:56 +08:00
Renaud 78e296afbb Revise directive parsing and processing.
Allow multi line comment using !store without procedure name (think about #if 0).
2021-09-10 10:10:19 +08:00
Renaud 81d6f76c78 Test maze scripts using subroutines instead of stored procedures. (Avoid leftover buffers after execution). 2021-09-08 11:05:51 +08:00
Renaud 296f0af96c !gosub
Use generic list deletion API.
Remove lines at parsing time.
2021-09-08 10:58:53 +08:00
Renaud 2674d40d4c Introduce generic list deletion API. 2021-09-08 10:54:07 +08:00
Renaud 0d0e2d86b2 Handle storing of procedure during parsing of buffer.
!store and :labels.
Aggressive parsing empty blank and comment lines.
2021-09-05 12:01:02 +08:00
Renaud 95118b61c8 Revise maze test scripts. 2021-09-01 09:40:34 +08:00
Renaud 60a56b74b0 Use lines instead of block Unicode characters.(poor rendering in some environments). 2021-08-31 12:57:37 +08:00
Renaud 64eb0d5deb Use explicit constants for smallest size of display rows and columns. 2021-08-31 12:55:10 +08:00
Renaud f96ace997f Fix terminal resizing when new postion of last modeline overlap top row of last window. 2021-08-30 18:09:58 +08:00
Renaud f010d63a95 Fix initialization of screen margin and scroll size. 2021-08-30 13:16:46 +08:00
Renaud 0cb1799786 Revise refresh of extended lines. 2021-08-30 12:30:29 +08:00
Renaud 0a8c28bc07 Revise display update and modeline, remove statis customization (MEMMAP, REVSTA). 2021-08-28 10:33:36 +08:00
Renaud 699dac8b27 Allocate screen memory on change of window size instead of one static huge allocation. 2021-08-24 16:00:32 +08:00
Renaud e2f7cc0566 Sanity check with customization CLEAN, RAMSIZE, RAMSHOW. 2021-08-24 12:17:40 +08:00
Renaud a370d748c4 Revise line primitives linstr() and lover() 2021-08-22 12:35:39 +08:00
Renaud 62e1109802 Relocate display specific MEMMAP customization. 2021-08-22 10:53:02 +08:00
Renaud bfb78e5382 Revise line primitives lalloc() and lnewline(). 2021-08-22 10:51:46 +08:00
Renaud ab34471d4d Fix &right to handle a count of Unicode characters. 2021-08-21 17:21:18 +08:00
Renaud cd2f848e0a Fix twiddle movement and at EOL with single Unicode. 2021-08-21 09:36:41 +08:00
Renaud 3d83877086 combined Unicode: forward-character, backward-character, delete-next-character, delete-previous-character. 2021-08-21 09:34:06 +08:00
Renaud 38aa6b97c8 Use more portable character for visible tabs due to mismatched width on Ubuntu. 2021-08-19 10:56:13 +08:00
Renaud 679d8d098b Temporary fix for WSL 2021-08-19 10:07:13 +08:00
Renaud e6921a8ed1 Centralize customization in defines.h instead of Makefile + estruct.h. 2021-08-18 16:54:35 +08:00
Renaud d99b7fcbac Revise terminal interfaces. 2021-08-18 11:35:17 +08:00
Renaud 5f3b42f448 Use gcc predefined in conditional compilation (__CYGWIN__, __SIZEOF_WCHAR_T__). 2021-08-18 09:37:47 +08:00
Renaud 18a0fbe57f Refactoring gtfun(), function evaluation core. 2021-08-16 17:18:51 +08:00
Renaud 2758464a2e $viewtab = TRUE to visualize hardcoded tabs.
Refactor &lef and & mid with stronger assertion on utf8_to_unicode().
2021-08-16 11:05:24 +08:00
46 changed files with 2122 additions and 2643 deletions

View File

@ -13,11 +13,6 @@ else
endif endif
export E Q 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 PROGRAM=ue
CC=gcc CC=gcc
@ -25,18 +20,7 @@ WARNINGS=-pedantic -Wall -Wextra -Wstrict-prototypes -Wno-unused-parameter
CFLAGS=-O2 $(WARNINGS) CFLAGS=-O2 $(WARNINGS)
LDFLAGS=-s LDFLAGS=-s
LIBS=-lcurses LIBS=-lcurses
DEFINES=-DAUTOCONF -DPROGRAM=$(PROGRAM) # -DNDEBUG DEFINES=-DPROGRAM=$(PROGRAM) -D_GNU_SOURCE # -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
BINDIR=/usr/bin BINDIR=/usr/bin
LIBDIR=/usr/lib LIBDIR=/usr/lib

View File

@ -1,6 +1,6 @@
# README # # 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/). https://git.kernel.org/pub/scm/editors/uemacs/uemacs.git/).
### Changes compare to uEmacs/PK ### ### 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 * Some defaults changed due to 'finger habits': ue instead of em, ^S in
commands mapping... commands mapping...
### Unicode (UTF-8) support ###
* gcc limitation on Windows (__WCHAR_WIDTH__ 16).
* Display of double and zero width characters ongoing.
### How to build ### ### How to build ###
* dependencies: gcc, gmake, ncurses-devel. * dependencies: gcc, gmake, ncurses-devel.
* make * make
### Badges ###
[![Coverity Status](
https://scan.coverity.com/projects/4449/badge.svg)](
https://scan.coverity.com/projects/4449)

View File

@ -1,13 +1,17 @@
## blindmaz.cmd -- solve maze by walking a left-handed blind mouse ## blindmaz.cmd -- solve maze by walking a left-handed blind mouse
#7 set $seed #7 set $seed
#execute-file maze.cmd # either maze.cmd, sharpmaz.cmd or floodmaz.cmd
execute-file 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 set %y $curline
end-of-line end-of-line
set %stopcol &sub $curcol 1 set %stopcol &sub $curcol 1
# X-Y offset for absolute direction: east, south, west, north
set %DX0 1 set %DX0 1
set %DY0 0 set %DY0 0
set %DX1 0 set %DX1 0
@ -17,54 +21,40 @@ set %DY2 0
set %DX3 0 set %DX3 0
set %DY3 -1 set %DY3 -1
set %dotc &asc "." set %absD 0 # absolute direction: looking EAST
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
!while &les %x %stopcol !while &les %x %stopcol
set %nD &mod &add %D 3 4 # Can go left? # try move on left, right or front
run probe set %relD 3 # 3, 0, 1, 2 == left, front, right, back
!if &seq %res FALSE !while &not &equ %relD 2
set %nD %D # Can go straight? set %newD &mod &add %absD %relD 4
run probe set %offX &ind &cat "%DX" %newD
!if &seq %res FALSE set %offY &ind &cat "%DY" %newD
set %nD &mod &add %D 1 4 # Can go right? set %nx &add %x %offX
run probe set %ny &add %y %offY
!if &seq %res FALSE set $curline %ny
set %D &mod &add %D 2 4 # Go back! 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 !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
!endif set %relD &mod &add %relD 1 4
!endwhile
# else turn around
set %absD &mod &add %absD 2 4 # face back!
:moveon
!endwhile !endwhile
beginning-of-file
set $curline 3 set $curcol &add %x -1
set $curcol 1
unmark-buffer unmark-buffer

View File

@ -1,8 +1,9 @@
/* buffer.c -- implements buffer.h */ /* buffer.c -- implements buffer.h */
#include "buffer.h" #include "buffer.h"
/* Buffer management. Some of the functions are internal, and some are actually attached to /* Buffer management. Some of the functions are internal, and some are
user keys. Like everyone else, they set hints for the display system. actually attached to user keys. Like everyone else, they set hints for
the display system.
modified by Petri Kutvonen modified by Petri Kutvonen
*/ */
@ -11,9 +12,9 @@
#include <string.h> #include <string.h>
#include "defines.h" #include "defines.h"
#include "estruct.h"
#include "file.h" #include "file.h"
#include "input.h" #include "input.h"
#include "list.h"
#include "mlout.h" #include "mlout.h"
#include "utf8.h" #include "utf8.h"
#include "util.h" #include "util.h"
@ -326,13 +327,12 @@ static unsigned int utf8_disp_len( const char *s) {
static int makelist( int iflag) { static int makelist( int iflag) {
buffer_p bp;
int s;
char line[ FNAMSTART + sizeof( fname_t)] ; char line[ FNAMSTART + sizeof( fname_t)] ;
blistp->b_flag &= ~BFCHG; /* Don't complain! Mute bclear() */ blistp->b_flag &= ~BFCHG; /* Don't complain! Mute bclear() */
if ((s = bclear(blistp)) != TRUE) /* Blow old text away */ int s = bclear( blistp) ; /* Blow old text away */
return s; if( s != TRUE)
return s ;
blistp->b_fname[ 0] = 0 ; /* in case of user override */ blistp->b_fname[ 0] = 0 ; /* in case of user override */
@ -346,19 +346,15 @@ static int makelist( int iflag) {
return FALSE ; return FALSE ;
/* output the list of buffers */ /* output the list of buffers */
for( bp = bheadp ; bp != NULL ; bp = bp->b_bufp) { /* For all buffers */ for( buffer_p bp = bheadp ; bp != NULL ; bp = bp->b_bufp) {
char *cp1, *cp2 ;
int c ; 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 */ /* skip invisible buffers if iflag is false */
if (((bp->b_flag & BFINVS) != 0) && (iflag != TRUE)) if (((bp->b_flag & BFINVS) != 0) && (iflag != TRUE))
continue; continue;
do_layout( line, bp->b_mode) ; 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) */ /* output status of ACTIVE flag ('@' when the file has been read in) */
*cp1++ = (bp->b_active == TRUE) ? '@' : ' ' ; *cp1++ = (bp->b_active == TRUE) ? '@' : ' ' ;
@ -370,9 +366,10 @@ static int makelist( int iflag) {
*cp1 = ((bp->b_flag & BFCHG) != 0) ? '*' : ' ' ; *cp1 = ((bp->b_flag & BFCHG) != 0) ? '*' : ' ' ;
/* Buffer size */ /* Buffer size */
nbytes = 0L; /* Count bytes in buf. */ long nbytes = 0L; /* Count bytes in buf. */
nlines = 0 ; long nlines = 0 ;
for( lp = lforw( bp->b_linep) ; lp != bp->b_linep ; lp = lforw( lp)) { for( line_p lp = lforw( bp->b_linep) ; lp != bp->b_linep ;
lp = lforw( lp)) {
nbytes += (long) llength(lp) + 1L; nbytes += (long) llength(lp) + 1L;
nlines += 1 ; nlines += 1 ;
} }
@ -385,8 +382,8 @@ static int makelist( int iflag) {
*cp1++ = ' ' ; *cp1++ = ' ' ;
/* Display buffer name */ /* Display buffer name */
cp2 = &bp->b_bname[ 0] ; char *cp2 = &bp->b_bname[ 0] ;
while ((c = *cp2++) != 0) while( (c = *cp2++) != 0)
*cp1++ = c; *cp1++ = c;
/* Pad with spaces to max buffer name length */ /* 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. updates that are required. Return TRUE if everything looks good.
*/ */
int bclear( buffer_p bp) { int bclear( buffer_p bp) {
line_p lp ;
int s ; int s ;
if( (bp->b_flag & (BFINVS | BFCHG)) == BFCHG /* regular and changed */ if( (bp->b_flag & (BFINVS | BFCHG)) == BFCHG /* regular and changed */
@ -536,13 +532,28 @@ int bclear( buffer_p bp) {
return s ; return s ;
bp->b_flag &= ~BFCHG ; /* Not changed */ bp->b_flag &= ~BFCHG ; /* Not changed */
while( (lp = lforw( bp->b_linep)) != bp->b_linep) line_p lp = bp->b_linep ;
lfree( lp) ; 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 ; return TRUE ;
} }

View File

@ -1,17 +1,63 @@
/* defines.h -- */ /* defines.h -- customization based on gcc predefined macroes */
#ifndef __DEFINES_H__ #ifndef __DEFINES_H__
#define __DEFINES_H__ #define __DEFINES_H__
/* Must define one of #if __unix__
USG | BSD # define UNIX 1
*/ # if __NetBSD__
#define USG 1 # define BSD 1
# define POSIX 1
#define PKCODE 1 # elif __linux__
#define SCROLLCODE 1 /* scrolling code P.K. */ # define USG 1
#define ENVFUNC 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 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 <stdlib.h> /* size_t */
void *allocate( size_t size) ;
void release( void *ptr) ;
# define malloc( sz) allocate(sz)
# define free( ptr) release( ptr)
#endif #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 */

562
display.c
View File

@ -1,8 +1,6 @@
/* display.c -- implements display.h */ /* display.c -- implements display.h */
#include "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 /* 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 ones that update the virtual display screen, and the ones that make the
physical display screen the same as the virtual display screen. These physical display screen the same as the virtual display screen. These
@ -11,19 +9,22 @@
Modified by Petri Kutvonen Modified by Petri Kutvonen
*/ */
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <locale.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "buffer.h" #include "buffer.h"
#include "estruct.h" #include "defines.h"
#include "input.h" #include "input.h"
#include "line.h" #include "line.h"
#include "termio.h" #include "termio.h"
#include "terminal.h" #include "terminal.h"
#include "version.h" #include "version.h"
#include "wrapper.h"
#include "utf8.h" #include "utf8.h"
#include "window.h" #include "window.h"
@ -45,33 +46,31 @@ typedef struct {
#define VFCOL 0x0010 /* color change requested */ #define VFCOL 0x0010 /* color change requested */
static video_p *vscreen ; /* Virtual screen. */ static video_p *vscreen ; /* Virtual screen. */
#if MEMMAP == 0 || SCROLLCODE
static video_p *pscreen ; /* Physical screen. */ static video_p *pscreen ; /* Physical screen. */
#endif
static int displaying = TRUE ;
#if UNIX
# include <signal.h>
#endif
#ifdef SIGWINCH #ifdef SIGWINCH
# include <sys/ioctl.h> # include <sys/ioctl.h>
/* for window size changes */ /* for window size changes */
int chg_width, chg_height ; int chg_width, chg_height ;
static int displaying = TRUE ;
static void sizesignal( int signr) ;
#endif #endif
static int currow ; /* Cursor row */ static int currow ; /* Cursor row */
static int curcol ; /* Cursor column */ static int curcol ; /* Cursor column */
static int vtrow = 0 ; /* Row location of SW cursor */ static int vtrow = 0 ; /* Row location of SW cursor */
static int vtcol = 0 ; /* Column 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 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 mpresf = FALSE ; /* TRUE if message in last line */
int scrollcount = 1 ; /* number of lines to scroll */ int scrollcount = 1 ; /* number of lines to scroll */
int discmd = TRUE ; /* display command flag */ int discmd = TRUE ; /* display command flag */
int disinp = TRUE ; /* display input characters (echo) */ 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 int reframe( window_p wp) ;
static void updone( window_p wp) ; static void updone( window_p wp) ;
@ -84,65 +83,95 @@ static void upddex( void) ;
static void updext( void) ; static void updext( void) ;
static void updgar( void) ; static void updgar( void) ;
static void updpos( void) ; static void updpos( void) ;
static int updateline( int row, video_p vp1, video_p vp2) ; static void updateline( int row) ;
static boolean updupd( boolean force_f) ; static void updupd( boolean force_f) ;
static void modeline( window_p wp) ; static void modeline( window_p wp) ;
static void mlputi( int i, int r) ; static void mlputi( int i, int r) ;
static void mlputli( long l, int r) ; static void mlputli( long l, int r) ;
static void mlputf( int s) ; static void mlputf( int s) ;
static void mlputs( const char *s) ; static void mlputs( const char *s) ;
#if SIGWINCH #if SIGWINCH
static int newscreensize( int h, int w) ; static void newscreensize( int h, int w) ;
#endif #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 /* Initialize the data structures used by the display code. The edge
vectors used to access the screens are set up. The operating system's 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 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 compile time. The original window has "WFCHG" set, so that it will get
completely redrawn on the first call to "update". 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 static int lastmrow ; /* remember mrow for later free */
pscreen = xmalloc( term.t_maxrow * sizeof( video_p )) ;
#endif static void vtalloc( int maxrow, int maxcol) {
for( int i = 0 ; i < term.t_maxrow ; ++i) { lastmrow = maxrow ; /* remember mrow for later free */
video_p vp = xmalloc( sizeof *vp + term.t_maxcol * sizeof( unicode_t)) ; 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 ; vp->v_flag = 0 ;
#if COLOR #if COLOR
vp->v_rfcolor = 7 ; vp->v_rfcolor = 7 ;
vp->v_rbcolor = 0 ; vp->v_rbcolor = 0 ;
#endif #endif
vscreen[ i] = vp ; vscreen[ i] = vp ;
#if MEMMAP == 0 || SCROLLCODE vp = xmalloc( sizeof *vp + maxcol * sizeof( unicode_t)) ;
vp = xmalloc( sizeof *vp + term.t_maxcol * sizeof( unicode_t)) ;
vp->v_flag = 0 ; vp->v_flag = 0 ;
pscreen[ i] = vp ; pscreen[ i] = vp ;
#endif
} }
} }
#if CLEAN void updmargin( void) {
/* free up all the dynamically allocated video structures */ #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) { void vtfree( void) {
for( int i = 0 ; i < term.t_maxrow ; ++i ) { /* as xmalloc bypass the malloc macro, we need bypass the free macro too */
free( vscreen[ i]) ; for( int i = 0 ; i < lastmrow ; ++i ) {
#if MEMMAP == 0 || SCROLLCODE (free)( vscreen[ i]) ;
free( pscreen[ i]) ; (free)( pscreen[ i]) ;
#endif
} }
free( vscreen) ; (free)( vscreen) ;
#if MEMMAP == 0 || SCROLLCODE (free)( pscreen) ;
free( pscreen) ;
#endif
} }
#endif
/* Clean up the virtual terminal system, in anticipation for a return to /* 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 ; vtcol += 1 ;
} }
static void vtputc( unicode_t c) { static void vtputuc( unicode_t c) {
/* In case somebody passes us a signed char.. */ /* In case somebody passes us a signed char.. */
if( c > 0x10FFFF) /* Let's assume this is due to sign extension */ // if( c > 0x10FFFF) /* Let's assume this is due to sign extension */
c &= 0xFF ; // c &= 0xFF ;
assert( c <= 0x10FFFF) ;
if( c == '\t') if( c == '\t') {
do { sane_vtputc( viewtab ? 0xBB : ' ') ; /* 0xBB: '»' */
while( ((vtcol + lbound) % tabwidth) != 0)
sane_vtputc( ' ') ; sane_vtputc( ' ') ;
} while( ((vtcol + taboff) % tabwidth) != 0) ; } else if( c < 0x20 || c == 0x7F) {
else if( c < 0x20 || c == 0x7F) {
sane_vtputc( '^') ; sane_vtputc( '^') ;
sane_vtputc( c ^ 0x40) ; sane_vtputc( c ^ 0x40) ;
} else if( c >= 0x80 && c <= 0xA0) { } else if( c >= 0x80 && c <= 0xA0) {
@ -224,7 +254,7 @@ static int vtputs( const char *s) {
unicode_t c ; unicode_t c ;
s += utf8_to_unicode( s, 0, 4, &c) ; s += utf8_to_unicode( s, 0, 4, &c) ;
vtputc( c) ; vtputuc( c) ;
n += utf8_width( c) ; n += utf8_width( c) ;
} }
@ -242,11 +272,11 @@ static void vteeol( void) {
vcp[ vtcol++] = ' ' ; vcp[ vtcol++] = ' ' ;
} }
/* upscreen: /* upscreen():
* user routine to force a screen update * user routine to force a screen update
* always finishes complete update * always finishes complete update
*/ */
BINDABLE( upscreen) { TBINDABLE( upscreen) {
update( TRUE) ; update( TRUE) ;
return TRUE ; return TRUE ;
} }
@ -264,23 +294,27 @@ static int scrflags ;
boolean force_f ; force update past type ahead? 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 TYPEAH && ! PKCODE
if( force_f == FALSE && typahead()) if( force_f == FALSE && typahead())
return TRUE ; return ;
#endif #endif
#if VISMAC == 0 #if VISMAC == 0
if( force_f == FALSE && kbdmode == PLAY) if( force_f == FALSE && kbdmode == PLAY)
return TRUE ; return ;
#endif #endif
#if SIGWINCH
displaying = TRUE ; displaying = TRUE ;
resize:
#endif
#if SCROLLCODE #if SCROLLCODE
/* first, propagate mode line changes to all instances of a buffer displayed /* first, propagate mode line changes to all instances of a buffer displayed
* in more than one window */ * in more than one window */
window_p wp ;
for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp)
if( wp->w_flag & WFMODE if( wp->w_flag & WFMODE
&& wp->w_bufp->b_nwnd > 1) && wp->w_bufp->b_nwnd > 1)
@ -318,11 +352,6 @@ boolean update( boolean force_f) {
/* recalc the current hardware cursor location */ /* recalc the current hardware cursor location */
updpos() ; updpos() ;
#if MEMMAP && ! SCROLLCODE
/* update the cursor and flush the buffers */
movecursor( currow, curcol - lbound) ;
#endif
/* check for lines to de-extend */ /* check for lines to de-extend */
upddex() ; upddex() ;
@ -336,12 +365,15 @@ boolean update( boolean force_f) {
/* update the cursor and flush the buffers */ /* update the cursor and flush the buffers */
movecursor( currow, curcol - lbound) ; movecursor( currow, curcol - lbound) ;
TTflush() ; TTflush() ;
displaying = FALSE ;
#if SIGWINCH #if SIGWINCH
while( chg_width || chg_height) if( chg_width || chg_height) {
newscreensize( chg_height, chg_width) ; newscreensize( chg_height, chg_width) ;
force_f = TRUE ;
goto resize ;
}
displaying = FALSE ;
#endif #endif
return TRUE ;
} }
@ -438,8 +470,10 @@ static void show_line( line_p lp) {
while( i < len) { while( i < len) {
unicode_t c ; unicode_t c ;
i += utf8_to_unicode( lp->l_text, i, len, &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 * window_p wp; window to update current line in
*/ */
static void updone( window_p wp) { static void updone( window_p wp) {
line_p lp ;
/* search down the line we want */ /* search down the line we want */
int sline = wp->w_toprow ; /* physical screen line to update */ 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)) for( lp = wp->w_linep ; lp != wp->w_dotp ; lp = lforw( lp))
++sline ; ++sline ;
@ -464,7 +499,6 @@ static void updone( window_p wp) {
vscreen[ sline]->v_rfcolor = wp->w_fcolor ; vscreen[ sline]->v_rfcolor = wp->w_fcolor ;
vscreen[ sline]->v_rbcolor = wp->w_bcolor ; vscreen[ sline]->v_rbcolor = wp->w_bcolor ;
#endif #endif
vteeol() ;
} }
@ -486,14 +520,14 @@ static void updall( window_p wp) {
/* if we are not at the end */ /* if we are not at the end */
show_line( lp) ; show_line( lp) ;
lp = lforw( lp) ; lp = lforw( lp) ;
} } else
vteeol() ;
/* on to the next one */ /* on to the next one */
#if COLOR #if COLOR
vscreen[ sline]->v_rfcolor = wp->w_fcolor ; vscreen[ sline]->v_rfcolor = wp->w_fcolor ;
vscreen[ sline]->v_rbcolor = wp->w_bcolor ; vscreen[ sline]->v_rbcolor = wp->w_bcolor ;
#endif #endif
vteeol() ;
++sline ; ++sline ;
} }
} }
@ -504,13 +538,12 @@ static void updall( window_p wp) {
This is the only update for simple moves. This is the only update for simple moves.
*/ */
static void updpos( void) { static void updpos( void) {
line_p lp ;
/* find the current row */ /* find the current row */
line_p lp = curwp->w_linep ;
currow = curwp->w_toprow ; currow = curwp->w_toprow ;
while( lp != curwp->w_dotp) { for( lp = curwp->w_linep ; lp != curwp->w_dotp ; lp = lforw( lp))
++currow ; ++currow ;
lp = lforw( lp) ;
}
/* find the current column */ /* find the current column */
curcol = 0 ; curcol = 0 ;
@ -551,7 +584,6 @@ static void upddex( void) {
|| (curcol < term.t_ncol - 1)) { || (curcol < term.t_ncol - 1)) {
vtmove( i, 0) ; vtmove( i, 0) ;
show_line( lp) ; show_line( lp) ;
vteeol() ;
/* this line no longer is extended */ /* this line no longer is extended */
vscreen[ i]->v_flag &= ~VFEXT ; vscreen[ i]->v_flag &= ~VFEXT ;
@ -572,18 +604,14 @@ static void upddex( void) {
static void updgar( void) { static void updgar( void) {
for( int i = 0 ; i < term.t_nrow ; ++i) { for( int i = 0 ; i < term.t_nrow ; ++i) {
vscreen[ i]->v_flag |= VFCHG ; vscreen[ i]->v_flag |= VFCHG ;
#if REVSTA
vscreen[ i]->v_flag &= ~VFREV ; vscreen[ i]->v_flag &= ~VFREV ;
#endif
#if COLOR #if COLOR
vscreen[ i]->v_fcolor = gfcolor ; vscreen[ i]->v_fcolor = gfcolor ;
vscreen[ i]->v_bcolor = gbcolor ; vscreen[ i]->v_bcolor = gbcolor ;
#endif #endif
#if MEMMAP == 0 || SCROLLCODE
unicode_t *txt = pscreen[ i]->v_text ; unicode_t *txt = pscreen[ i]->v_text ;
for( int j = 0 ; j < term.t_ncol ; ++j) for( int j = 0 ; j < term.t_ncol ; ++j)
txt[ j] = ' ' ; txt[ j] = ' ' ;
#endif
} }
movecursor( 0, 0) ; /* Erase the screen. */ movecursor( 0, 0) ; /* Erase the screen. */
@ -601,7 +629,7 @@ static void updgar( void) {
* *
* int force; forced update flag * int force; forced update flag
*/ */
static boolean updupd( boolean force_f) { static void updupd( boolean force_f) {
#if SCROLLCODE #if SCROLLCODE
if( scrflags & WFKILLS) if( scrflags & WFKILLS)
scrolls( FALSE) ; scrolls( FALSE) ;
@ -613,23 +641,15 @@ static boolean updupd( boolean force_f) {
#endif #endif
for( int i = 0 ; i < term.t_nrow ; ++i) { for( int i = 0 ; i < term.t_nrow ; ++i) {
video_p vp1 = vscreen[ i] ;
/* for each line that needs to be updated */ /* 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 TYPEAH && ! PKCODE
if( force_f == FALSE && typahead()) if( force_f == FALSE && typahead())
return TRUE ; return TRUE ;
#endif #endif
#if MEMMAP && ! SCROLLCODE updateline( i) ;
updateline( i, vp1) ;
#else
updateline( i, vp1, pscreen[ i]) ;
#endif
} }
} }
return TRUE ;
} }
#if SCROLLCODE #if SCROLLCODE
@ -731,12 +751,10 @@ static int scrolls( int inserts) {
vpp->v_flag = vpv->v_flag ; /* XXX */ vpp->v_flag = vpv->v_flag ; /* XXX */
if( vpp->v_flag & VFREV) { if( vpp->v_flag & VFREV) {
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) { if( inserts) {
from = target ; from = target ;
to = match ; to = match ;
@ -744,7 +762,7 @@ static int scrolls( int inserts) {
from = target + count ; from = target + count ;
to = match + count ; to = match + count ;
} }
#if MEMMAP == 0
for( i = from ; i < to ; i++) { for( i = from ; i < to ; i++) {
unicode_t *txt ; unicode_t *txt ;
txt = pscreen[ i]->v_text ; txt = pscreen[ i]->v_text ;
@ -752,9 +770,10 @@ static int scrolls( int inserts) {
txt[ j] = ' ' ; txt[ j] = ' ' ;
vscreen[ i]->v_flag |= VFCHG ; vscreen[ i]->v_flag |= VFCHG ;
} }
#endif
return TRUE ; return TRUE ;
} }
return FALSE ; return FALSE ;
} }
@ -791,30 +810,20 @@ static int endofline( unicode_t *s, int n) {
/* updext: /* updext:
* update the extended line which the cursor is currently update the extended line which the cursor is currently on at a column
* on at a column greater than the terminal width. The line greater than the terminal width. The line will be scrolled right or
* will be scrolled right or left to let the user see where left to let the user see where the cursor is.
* the cursor is
*/ */
static void updext( void) { 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 */ /* calculate what column the real cursor will end up in */
rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin ; lbound = curcol - ((curcol - term.t_ncol) % term.t_scrsiz + term.t_margin) ;
taboff = lbound = curcol - rcursor + 1 ;
/* scan through the line outputing characters to the virtual screen */ /* scan through the line outputing characters to the virtual screen */
/* once we reach the left edge */ /* once we reach the left edge */
vtmove( currow, -lbound) ; /* start scanning offscreen */ vtmove( currow, -lbound) ; /* start scanning offscreen */
lp = curwp->w_dotp ; /* line to output */ show_line( curwp->w_dotp) ;
show_line( lp) ;
/* truncate the virtual line, restore tab offset */ /* put a '$' in column 1 */
vteeol() ;
taboff = 0 ;
/* and put a '$' in column 1 */
vscreen[ currow]->v_text[ 0] = '$' ; vscreen[ currow]->v_text[ 0] = '$' ;
} }
@ -823,114 +832,62 @@ static void updext( void) {
* character sequences; we are using VT52 functionality. Update the physical * character sequences; we are using VT52 functionality. Update the physical
* row and column variables. It does try an exploit erase to end of line. * 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() /* updateline()
* *
* int row ; row of screen to update * 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) { static void updateline( int row) {
/* UPDATELINE code for all other versions */ video_p vp1 = vscreen[ row] ;
vp1->v_flag &= ~VFCHG ; /* flag this line as updated */
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 */
/* set up pointers to virtual and physical lines */ /* set up pointers to virtual and physical lines */
cp1 = &vp1->v_text[ 0] ; unicode_t *inp = vp1->v_text ;
cp2 = &vp2->v_text[ 0] ; unicode_t *out = pscreen[ row]->v_text ;
#if COLOR #if COLOR
TTforg( vp1->v_rfcolor) ; TTforg( vp1->v_rfcolor) ;
TTbacg( vp1->v_rbcolor) ; TTbacg( vp1->v_rbcolor) ;
#endif #endif
#if REVSTA | COLOR /* do a re-write of the entire line if there is a request to toggle the
/* do a re-write of the entire line if it is reverse or there * reverse status */
** is a request to change the reverse status */ int rev = (vp1->v_flag & VFREV) == VFREV ;
rev = (vp1->v_flag & VFREV) == VFREV ; if( rev != ((vp1->v_flag & VFREQ) == VFREQ)
req = (vp1->v_flag & VFREQ) == VFREQ ;
if( req || (req != rev)
#if COLOR #if COLOR
|| (vp1->v_fcolor != vp1->v_rfcolor) || (vp1->v_fcolor != vp1->v_rfcolor)
|| (vp1->v_bcolor != vp1->v_rbcolor) || (vp1->v_bcolor != vp1->v_rbcolor)
#endif #endif
) { ) {
movecursor( row, 0) ; /* Go to start of line. */ 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 /* scan through the line and dump it to the screen and
the virtual screen array */ the virtual screen array */
while( ttcol < term.t_ncol) { while( ttcol < term.t_ncol) {
/* TODO: handle double width unicode char at last screen col */ /* TODO: handle double width unicode char at last screen col */
unicode_t c = *cp1++ ; unicode_t c = *out++ = *inp++ ;
TTputc( c) ; TTputc( c) ;
ttcol += utf8_width( c) ; ttcol += _utf8_width( c) ; /* filtered by vtputuc */
*cp2++ = c ;
} }
TTrev( FALSE) ; /* turn rev video off */ TTrev( FALSE) ; /* turn rev video off */
/* update the needed flags */ /* update the needed flags */
vp1->v_flag &= ~VFCHG ; vp1->v_flag ^= VFREV ;
if( req)
vp1->v_flag |= VFREV ;
else
vp1->v_flag &= ~VFREV ;
#if COLOR #if COLOR
vp1->v_fcolor = vp1->v_rfcolor ; vp1->v_fcolor = vp1->v_rfcolor ;
vp1->v_bcolor = vp1->v_rbcolor ; vp1->v_bcolor = vp1->v_rbcolor ;
#endif #endif
return TRUE ; return ;
} }
#endif
/* advance past any common chars at the left */ /* advance past any common chars at the left */
while( cp1 != &vp1->v_text[ term.t_ncol] && cp1[ 0] == cp2[ 0]) { unicode_t *end = &vp1->v_text[ term.t_ncol] ;
++cp1 ; int startcol = 0 ;
++cp2 ; 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 /* 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. * 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 both lines are the same, no update needs to be done */
if( cp1 == &vp1->v_text[ term.t_ncol]) { if( inp == end)
vp1->v_flag &= ~VFCHG ; /* flag this line is changed */ return ;
return TRUE ;
}
/* find out if there is a match on the right */ /* find out if there is a match on the right */
nbflag = FALSE ; int nbflag = FALSE ; /* non-blanks to the right flag? */
cp3 = &vp1->v_text[ term.t_ncol] ;
cp4 = &vp2->v_text[ term.t_ncol] ;
while( cp3[ -1] == cp4[ -1]) { unicode_t *nbp = &pscreen[ row]->v_text[ term.t_ncol] ;
--cp3 ; while( end[ -1] == nbp[ -1]) {
--cp4 ; --end ;
if( cp3[ 0] != ' ') /* Note if any nonblank */ --nbp ;
if( *end != ' ') /* Note if any nonblank */
nbflag = TRUE ; /* in right match. */ nbflag = TRUE ; /* in right match. */
} }
cp5 = cp3 ; nbp = end ;
/* Erase to EOL ? */ /* Erase to EOL ? */
if( nbflag == FALSE && eolexist == TRUE && (req != TRUE)) { if( nbflag == FALSE && eolexist == TRUE && (rev != TRUE)) {
while( cp5 != cp1 && cp5[ -1] == ' ') while( nbp != inp && nbp[ -1] == ' ')
--cp5 ; --nbp ;
if( cp3 - cp5 <= 3) /* Use only if erase is */ if( end - nbp <= 3) /* Use only if erase is */
cp5 = cp3 ; /* fewer characters. */ nbp = end ; /* fewer characters. */
} }
movecursor( row, cp1 - &vp1->v_text[ 0]) ; /* Go to start of line. */ movecursor( row, startcol) ; /* Go to start of line change */
#if REVSTA
TTrev( rev) ; TTrev( rev) ;
#endif
while( cp1 != cp5) { /* Ordinary. */ while( inp != nbp) { /* Copy */
unicode_t c = *cp1++ ; unicode_t c = *out++ = *inp++ ;
TTputc( c) ; TTputc( c) ;
ttcol += utf8_width( c) ; ttcol += utf8_width( c) ;
*cp2++ = c ;
} }
if( cp5 != cp3) { /* Erase. */ if( inp != end) { /* Erase */
TTeeol() ; TTeeol() ;
while( cp1 != cp3) do
*cp2++ = *cp1++ ; *out++ = ' ' ;
while( ++inp != end) ;
} }
#if REVSTA
TTrev( FALSE) ; 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 /* Redisplay the mode line for the window pointed to by the "wp". This is
* only routine that has any idea of how the modeline is formatted. You can the only routine that has any idea of how the modeline is formatted.
* change the modeline format by hacking at this routine. Called by "update" You can change the modeline format by hacking at this routine. Called
* any time there is a dirty window. by "update" any time there is a dirty window.
*/ */
static void modeline( window_p wp) { static void modeline( window_p wp) {
int n ; /* cursor position count */ char tline[] = " % " ; /* formatting buffer for percentage */
buffer_p bp ;
int i ; /* loop index */
int lchar ; /* character to draw line in buffer with */
int firstm ; /* is this the first mode? */
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. */ vscreen[ n]->v_flag |= VFCHG | VFREQ | VFCOL ; /* Redraw next time. */
#if COLOR #if COLOR
vscreen[ n]->v_rfcolor = 0 ; /* black on */ vscreen[ n]->v_rfcolor = 0 ; /* black on */
vscreen[ n]->v_rbcolor = 7 ; /* white..... */ vscreen[ n]->v_rbcolor = 7 ; /* white..... */
#endif #endif
vtmove( n, 0) ; /* Seek to right line. */ vtmove( n, 0) ; /* Seek to right line. */
if( wp == curwp) /* mark the current buffer */ int lchar = "-= -"[ 2 * revexist + (wp == curwp)] ; /* pick bg character */
#if PKCODE && REVSTA
lchar = '-' ;
#else
lchar = '=' ;
#endif
else
#if REVSTA
if( revexist)
lchar = ' ' ;
else
#endif
lchar = '-' ;
bp = wp->w_bufp ; buffer_p bp = wp->w_bufp ;
vtputc( ((bp->b_flag & BFTRUNC) != 0) ? '#' : lchar) ; /* truncated? */ vtputuc( ((bp->b_flag & BFTRUNC) != 0) ? '#' : lchar) ; /* truncated? */
vtputc( ((bp->b_flag & BFCHG) != 0) ? '*' : lchar) ; /* changed? */ vtputuc( ((bp->b_flag & BFCHG) != 0) ? '*' : lchar) ; /* changed? */
vtputc( ' ') ; vtputuc( ' ') ;
if( n == term.t_nrow - 1) if( n == term.t_nrow - 1)
n = 3 + vtputs( PROGRAM_NAME_UTF8 " " VERSION ": ") ; n = 3 + vtputs( PROGRAM_NAME_UTF8 " " VERSION ": ") ;
@ -1040,105 +972,75 @@ static void modeline( window_p wp) {
n += vtputs( bp->b_bname) ; n += vtputs( bp->b_bname) ;
n += vtputs( " (") ; n += vtputs( " (") ;
/* display the modes */ /* display the modes */
int pos = n ;
if( (bp->b_flag & BFTRUNC) != 0) { if( (bp->b_flag & BFTRUNC) != 0)
firstm = FALSE ;
n += vtputs( "Truncated") ; 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( wp->w_bufp->b_mode & (1 << i)) {
if( firstm != TRUE) if( n > pos) {
n += vtputs( " ") ; vtputuc( ' ') ;
else n += 1 ;
firstm = FALSE ; }
n += vtputs( modename[ i]) ; n += vtputs( modename[ i]) ;
} }
n += vtputs( ") ") ; n += vtputs( ") ") ;
#if PKCODE
if( bp->b_fname[ 0] != 0 && strcmp( bp->b_bname, bp->b_fname) != 0) { 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) ; n += vtputs( bp->b_fname) ;
vtputc(' ') ; vtputuc( ' ') ;
++n ; ++n ;
} }
while( n < term.t_ncol) { /* Pad to full width. */ while( n < term.t_ncol) { /* Pad to full width. */
vtputc( lchar) ; vtputuc( lchar) ;
++n ; ++n ;
} }
{ /* determine if top line, bottom line, or both are visible */ /* determine if top line, bottom line, or both are visible */
line_p lp = wp->w_linep ; char *msg = NULL ;
int rows = wp->w_ntrows ;
char *msg = NULL ;
char tline[ 6] ; /* buffer for part of mode line */
vtcol -= 7 ; /* strlen(" top ") plus a couple */ if( wp->w_linep == wp->w_bufp->b_linep)
while( rows--) { 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) ; lp = lforw( lp) ;
if( lp == wp->w_bufp->b_linep) { if( lp == wp->w_bufp->b_linep) {
msg = " Bot " ; msg = msg ? " All " : " End " ;
break ; 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) { if( !msg) {
line_p lp ; /* buffer is not empty, both first and last line not in window */
int numlines, predlines ; n = 0 ; /* count of lines in buffer */
pos = 0 ; /* line number of the top line in window */
lp = lforw( bp->b_linep) ; for( lp = lforw( bp->b_linep) ; lp != bp->b_linep ;
numlines = 0 ; lp = lforw( lp)) {
predlines = 0 ; n += 1 ;
while( lp != bp->b_linep) { if( lp == wp->w_linep)
if( lp == wp->w_linep) { pos = n ;
predlines = numlines ;
}
++numlines ;
lp = lforw( lp) ;
} }
if( wp->w_dotp == bp->b_linep) {
msg = " Bot " ;
} else {
int ratio = 0 ;
if( numlines != 0) pos = (100L * pos) / n ;
ratio = (100L * predlines) / numlines ; tline[ 2] = pos % 10 + '0' ;
if( ratio > 99) pos /= 10 ;
ratio = 99 ; if( pos)
tline[ 1] = pos + '0' ;
tline[ 0] = ' ' ; msg = tline ;
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 ;
}
} }
n += vtputs( msg) ;
} }
vtcol -= 7 ; /* strlen(" top ") plus a couple */
vtputs( msg) ;
} }
void upmode( void) { /* update all the mode lines */ void upmode( void) { /* update all the mode lines */
@ -1402,7 +1304,7 @@ void getscreensize( int *widthp, int *heightp) {
} }
#ifdef SIGWINCH #ifdef SIGWINCH
void sizesignal( int signr) { static void sizesignal( int signr) {
int w, h ; int w, h ;
int old_errno = errno ; int old_errno = errno ;
@ -1411,33 +1313,37 @@ void sizesignal( int signr) {
if( h > 0 && w > 0) { if( h > 0 && w > 0) {
term.t_mrow = h = h < term.t_maxrow ? h : term.t_maxrow ; term.t_mrow = h = h < term.t_maxrow ? h : term.t_maxrow ;
term.t_mcol = w = w < term.t_maxcol ? w : term.t_maxcol ; term.t_mcol = w = w < term.t_maxcol ? w : term.t_maxcol ;
if( h - 1 != term.t_nrow || w != term.t_ncol) if( h - 1 != term.t_nrow || w != term.t_ncol) {
newscreensize( h, w) ; if( displaying) {
chg_width = w ;
chg_height = h ;
} else {
newscreensize( h, w) ;
update( TRUE) ;
}
}
} }
signal( SIGWINCH, sizesignal) ; signal( SIGWINCH, sizesignal) ;
errno = old_errno ; errno = old_errno ;
} }
static int newscreensize( int h, int w) { static void newscreensize( int h, int w) {
/* do the change later */
if( displaying) {
chg_width = w ;
chg_height = h ;
return FALSE ;
}
chg_width = chg_height = 0 ; chg_width = chg_height = 0 ;
vtfree() ;
if( h < MINROWS)
h = MINROWS ;
if( w < MINCOLS)
w = MINCOLS ;
vtalloc( h, w) ;
if( h <= term.t_mrow) if( h <= term.t_mrow)
newsize( TRUE, h) ; newsize( TRUE, h) ;
if( w <= term.t_mcol) if( w <= term.t_mcol)
newwidth( TRUE, w) ; newwidth( TRUE, w) ;
update( TRUE) ;
return TRUE ;
} }
#endif #endif

View File

@ -4,10 +4,13 @@
#include <stdarg.h> #include <stdarg.h>
#include "estruct.h" #include "defines.h" /* UNIX */
#include "names.h" /* BINDABLE() */ #include "names.h" /* BINDABLE() */
#include "utf8.h" /* unicode_t */ #include "utf8.h" /* unicode_t */
#define MINROWS 3
#define MINCOLS 10
extern int mpresf ; /* Stuff in message line */ extern int mpresf ; /* Stuff in message line */
extern int scrollcount ; /* number of lines to scroll */ extern int scrollcount ; /* number of lines to scroll */
extern int discmd ; /* display command flag */ 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 gfcolor ; /* global forgrnd color (white) */
extern int gbcolor ; /* global backgrnd color (black) */ extern int gbcolor ; /* global backgrnd color (black) */
/* global variables */
extern boolean viewtab ; /* $viewtab = TRUE to visualize hardcoded tab */
/* Bindable functions */ /* Bindable functions */
BINDABLE( upscreen) ; TBINDABLE( upscreen) ;
void vtinit( void) ; void vtinit( void) ;
void vtfree( void) ; void vtfree( void) ;
void vttidy( void) ; void vttidy( void) ;
boolean update( boolean force_f) ; void update( boolean force_f) ;
void updmargin( void) ;
void upmode( void) ; void upmode( void) ;
void movecursor( int row, int col) ; void movecursor( int row, int col) ;
void mlerase( void) ; void mlerase( void) ;
@ -37,8 +44,6 @@ void getscreensize( int *widthp, int *heightp) ;
# include <signal.h> # include <signal.h>
# ifdef SIGWINCH # ifdef SIGWINCH
extern int chg_width, chg_height ; extern int chg_width, chg_height ;
void sizesignal( int signr) ;
# endif # endif
#endif #endif

View File

@ -19,7 +19,7 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
=> THE VERY BASICS => THE VERY BASICS
Notations: ^X means <Ctrl> and X. The <Meta> key is <Esc> on most systems. Notations: ^X means <Ctrl> and X. The <Meta> key is <Esc> 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 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 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 => FILE COMMANDS
Find file ............. ^X ^F Quick exit ............ Meta Z 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 Insert file ........... ^X ^I
Change file name ...... ^X N Filter buffer ......... ^X # Change file name ...... ^X N Filter buffer ......... ^X #
Save file ............. ^X ^D 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 => ACCESSING THE OPERATING SYSTEM
Quick exit ............ Meta Z :: Write out all changed buffers and exit. 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. I shell ............... ^X C :: Start a new command processor.
Shell command ......... ^X ! :: Execute one operating system command. Shell command ......... ^X ! :: Execute one operating system command.
Pipe command .......... ^X @ :: Pipe command results to a new buffer. * Pipe command .......... ^X @ :: Pipe command results to a new buffer.
Filter buffer ......... ^X # :: Filter buffer through a program. * Filter buffer ......... ^X # :: Filter buffer through a program.
Execute program ....... ^X $ :: * Not under VMS. Execute program ....... ^X $ ::
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
=> MACRO COMMANDS => MACRO COMMANDS
Begin macro ........... ^X ( Begin macro ........... ^X (

310
emacs.rc
View File

@ -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. ; 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 &not &seq $progname µEMACS
; uemacs/PK and MicroEMACS
set $discmd TRUE
!return
!endif
!if &seq $progname "µEMACS" set $tab 4
!force execute-file &cat $HOME "/.uerc" # 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 !else
set %F1 FNP
; First, try to resolve if we are on a PC ... yes, this is a kludge set %Home FNH
set %End FNF
!if &seq $sres "NORMAL"
set %system "OTHER"
!else
set %system "PC"
!endif !endif
!if &seq %system "PC" !store 40
set $discmd FALSE
; 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"
!if &not &seq $cbufname "emacs.hlp" !if &not &seq $cbufname "emacs.hlp"
write-message "(Loading Help)" write-message "(Loading Help)"
!force help !force help
!force 8 resize-window !if &not &seq $cbufname "emacs.hlp"
!if &seq %system "PC" write-message "(Failed to load Help)"
!if &seq &env "EMACS_BW" ""
add-mode "red"
!endif
bind-to-key execute-macro-38 FNI
bind-to-key execute-macro-37 FNQ
!else !else
bind-to-key execute-macro-38 FN5 !force 8 resize-window
bind-to-key execute-macro-37 FN6 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 !endif
beginning-of-line
2 forward-character
1 redraw-display
save-window
!if &seq %system "PC"
set %hlpupdn "<PgUp> / <PgDn>"
set %hlphelp "<F1>"
!else
set %hlpupdn "<Prev Scrn> / <Next Scrn>"
set %hlphelp "<Help>"
!endif
execute-macro-39
!else !else
set %hlpcode &lef $line 2 set %hlpcode &lef $line 2
!if &seq %hlpcode ".." !if &seq %hlpcode ".."
@ -117,33 +55,29 @@ bind-to-key next-window FN^X
beginning-of-line beginning-of-line
2 forward-character 2 forward-character
1 redraw-display 1 redraw-display
execute-macro-39 run helponhelp
!else !else
!if &seq %system "PC" !force search-reverse "=>"
bind-to-key previous-page FNI bind-to-key previous-page FN5
bind-to-key next-page FNQ bind-to-key next-page FN6
!else bind-to-key beginning-of-file %Home
bind-to-key previous-page FN5 bind-to-key end-of-file %End
bind-to-key next-page FN6
!endif
!force restore-window
!force delete-window !force delete-window
clear-message-line clear-message-line
!endif !endif
!endif !endif
set $discmd "TRUE" set $discmd TRUE
!endm !endm
bind-to-key execute-macro-40 M-? bind-to-key execute-macro-40 M-?
!if &seq %system "PC" bind-to-key execute-macro-40 %F1
bind-to-key execute-macro-40 FN; bind-to-key execute-macro-40 M-O
!else bind-to-key beginning-of-file %Home
bind-to-key execute-macro-40 FNh bind-to-key end-of-file %End
!endif
; Help on Help
39 store-macro ## Help on Help
!store helponhelp
!if &seq &rig $line 5 "INDEX" !if &seq &rig $line 5 "INDEX"
write-message &cat "Select topic from list and press " %hlphelp write-message &cat "Select topic from list and press " %hlphelp
!else !else
@ -151,150 +85,72 @@ bind-to-key execute-macro-40 M-?
!endif !endif
!endm !endm
; Previous help page
38 store-macro ## Previous help page
!store 39
!if &seq $cbufname "emacs.hlp" !if &seq $cbufname "emacs.hlp"
beginning-of-line beginning-of-line
!force search-reverse "=>" !force search-reverse "=>"
2 forward-character 2 forward-character
1 redraw-display 1 redraw-display
execute-macro-39 run helponhelp
!else !else
previous-page previous-page
!endif !endif
!endm !endm
; Next help page
37 store-macro ## Next help page
!store 38
!if &seq $cbufname "emacs.hlp" !if &seq $cbufname "emacs.hlp"
beginning-of-line beginning-of-line
2 forward-character 2 forward-character
!force search-forward "=>" !force search-forward "=>"
1 redraw-display 1 redraw-display
execute-macro-39 run helponhelp
!else !else
next-page next-page
!endif !endif
!endm !endm
; Set up auto CMODE !store 37
beginning-of-file
!if &seq $cbufname "emacs.hlp"
execute-macro-39
!endif
!endm
36 store-macro !store 36
!if &seq &mid $cfname 1 7 "/tmp/Re" end-of-file
add-mode "wrap" !if &seq $cbufname "emacs.hlp"
!return execute-macro-39
!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 !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 !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 bind-to-key newline ^J
; uEmacs/PK specific initialization
!if &seq $progname "uEmacs/PK" !if &or &sin $LANG "UTF-8" &sin $LANG "utf8"
; 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
add-global-mode "utf-8" add-global-mode "utf-8"
!endif !endif
!if &gre &sin $LANG "utf8" 0 set $discmd TRUE
add-global-mode "utf-8"
!endif
add-global-mode "utf-8"
!endif
set $discmd "TRUE"

135
estruct.h
View File

@ -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 <stdlib.h>
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 */

580
eval.c
View File

@ -8,7 +8,6 @@
*/ */
#include <assert.h> #include <assert.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
@ -16,8 +15,8 @@
#include "basic.h" #include "basic.h"
#include "bind.h" #include "bind.h"
#include "buffer.h" #include "buffer.h"
#include "defines.h"
#include "display.h" #include "display.h"
#include "estruct.h"
#include "exec.h" #include "exec.h"
#include "execute.h" #include "execute.h"
#include "flook.h" #include "flook.h"
@ -31,8 +30,6 @@
#include "version.h" #include "version.h"
#include "window.h" #include "window.h"
#define MAXVARS 255
/* Macro argument token types */ /* Macro argument token types */
#define TKNUL 0 /* end-of-string */ #define TKNUL 0 /* end-of-string */
@ -47,7 +44,6 @@
#define TKSTR 9 /* quoted string literal */ #define TKSTR 9 /* quoted string literal */
#define TKCMD 10 /* command name */ #define TKCMD 10 /* command name */
static int gettyp( char *token) ;
/* Emacs global flag bit definitions (for gflags). */ /* Emacs global flag bit definitions (for gflags). */
/* if GFREAD is set, current buffer will be set on first file (read in) */ /* 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 */ 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. */ /* User variables ******************************************/
#define NVSIZE 10 #define MAXVARS 255
#define NVSIZE 10 /* Max #chars in a var name. */
/* Structure to hold user variables and their definitions. */ /* Structure to hold user variables and their definitions. */
struct user_variable { static struct {
char u_name[NVSIZE + 1]; /* name of user variable */ char u_name[ NVSIZE + 1] ; /* name of user variable */
char *u_value; /* value (string) */ char *u_value ; /* value (string) */
}; } uv[ MAXVARS + 1] ;
static char errorm[] = "ERROR" ; /* error literal */ static char errorm[] = "ERROR" ; /* error literal */
@ -129,6 +127,7 @@ static const char *envars[] = {
"rval", /* child process return value */ "rval", /* child process return value */
"tab", /* tab width, 1... */ "tab", /* tab width, 1... */
"hardtab", /* TRUE for hard coded tab, FALSE for soft ones */ "hardtab", /* TRUE for hard coded tab, FALSE for soft ones */
"viewtab", /* TRUE to visualize hard coded tabs */
"overlap", "overlap",
"jump", "jump",
#if SCROLLCODE #if SCROLLCODE
@ -136,7 +135,7 @@ static const char *envars[] = {
#endif #endif
}; };
/* And its preprocesor definitions. */ /* And its preprocessor definitions. */
#define EVFILLCOL 0 #define EVFILLCOL 0
#define EVPAGELEN 1 #define EVPAGELEN 1
@ -177,9 +176,10 @@ static const char *envars[] = {
#define EVRVAL 36 #define EVRVAL 36
#define EVTAB 37 #define EVTAB 37
#define EVHARDTAB 38 #define EVHARDTAB 38
#define EVOVERLAP 39 #define EVVIEWTAB 39
#define EVSCROLLCOUNT 40 #define EVOVERLAP 40
#define EVSCROLL 41 #define EVSCROLLCOUNT 41
#define EVSCROLL 42
enum function_type { enum function_type {
NILNAMIC = 0, NILNAMIC = 0,
@ -188,6 +188,9 @@ enum function_type {
TRINAMIC = (3 << 6) TRINAMIC = (3 << 6)
} ; } ;
#define ARGCOUNT( ft) (ft >> 6)
#define FUNID( ft) (ft & ((1 << 6) - 1))
enum function_code { enum function_code {
UFADD = 0, UFSUB, UFTIMES, UFDIV, UFMOD, UFNEG, UFADD = 0, UFSUB, UFTIMES, UFDIV, UFMOD, UFNEG,
UFCAT, UFLEFT, UFRIGHT, UFMID, UFNOT, UFEQUAL, UFCAT, UFLEFT, UFRIGHT, UFMID, UFNOT, UFEQUAL,
@ -202,7 +205,7 @@ enum function_code {
static struct { static struct {
const char f_name[ 4] ; const char f_name[ 4] ;
const int f_type ; const int f_type ;
} funcs[] = { } const funcs[] = {
{ "abs", UFABS | MONAMIC }, /* absolute value of a number */ { "abs", UFABS | MONAMIC }, /* absolute value of a number */
{ "add", UFADD | DYNAMIC }, /* add two numbers together */ { "add", UFADD | DYNAMIC }, /* add two numbers together */
{ "and", UFAND | DYNAMIC }, /* logical and */ { "and", UFAND | DYNAMIC }, /* logical and */
@ -212,7 +215,7 @@ static struct {
{ "bno", UFBNOT | MONAMIC }, /* bitwise not */ { "bno", UFBNOT | MONAMIC }, /* bitwise not */
{ "bor", UFBOR | DYNAMIC }, /* bitwise or 9-10-87 jwm */ { "bor", UFBOR | DYNAMIC }, /* bitwise or 9-10-87 jwm */
{ "bxo", UFBXOR | DYNAMIC }, /* bitwise xor 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 */ { "chr", UFCHR | MONAMIC }, /* integer to char conversion */
{ "div", UFDIV | DYNAMIC }, /* division */ { "div", UFDIV | DYNAMIC }, /* division */
{ "env", UFENV | MONAMIC }, /* retrieve a system environment var */ { "env", UFENV | MONAMIC }, /* retrieve a system environment var */
@ -237,7 +240,7 @@ static struct {
{ "sgr", UFSGREAT | DYNAMIC }, /* string logical greater than */ { "sgr", UFSGREAT | DYNAMIC }, /* string logical greater than */
{ "sin", UFSINDEX | DYNAMIC }, /* find the index of one string in another */ { "sin", UFSINDEX | DYNAMIC }, /* find the index of one string in another */
{ "sle", UFSLESS | DYNAMIC }, /* string logical less than */ { "sle", UFSLESS | DYNAMIC }, /* string logical less than */
{ "sub", UFSUB | DYNAMIC }, /* subtraction */ { "sub", UFSUB | DYNAMIC }, /* substraction */
{ "tim", UFTIMES | DYNAMIC }, /* multiplication */ { "tim", UFTIMES | DYNAMIC }, /* multiplication */
{ "tru", UFTRUTH | MONAMIC }, /* Truth of the universe logical test */ { "tru", UFTRUTH | MONAMIC }, /* Truth of the universe logical test */
{ "upp", UFUPPER | MONAMIC }, /* uppercase string */ { "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, /* When emacs' command interpetor needs to get a variable's name,
* rather than it's value, it is passed back as a variable description * 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. * structure. The v_num field is a index into the appropriate variable table.
*/ */
struct variable_description { typedef struct {
int v_type; /* Type of variable. */ int v_type ; /* Type of variable. */
int v_num; /* Ordinal pointer to variable in list. */ int v_num ; /* Ordinal pointer to variable in list. */
}; } variable_description ;
static void findvar( char *var, struct variable_description *vd, int size) ; static void findvar( char *var, variable_description *vd, int size) ;
static int svar( struct variable_description *var, char *value) ; static int svar( variable_description *var, char *value) ;
static char *i_to_a( int i) ; static const char *i_to_a( int i) ;
/* /*
* putctext: * putctext:
@ -307,25 +307,22 @@ void varinit(void)
seed = time( NULL) ; seed = time( NULL) ;
} }
/*
* Evaluate a function. /* Evaluate a function.
* *
* @fname: name of function to evaluate. * @fname: name of function to evaluate.
*/ */
static const char *gtfun( char *fname) { static const char *gtfun( char *fname) {
unsigned fnum ; /* index to function to eval */ char *argv[ 3] ;
char *arg1 ; /* value of first argument */ const char *retstr ; /* return value */
char *arg2 ; /* value of second argument */ int i ;
char *arg3 ; /* last argument */
const char *retstr ; /* return value */
int low, high ; /* binary search indexes */
/* look the function up in the function table */ /* look the function up in the function table */
fname[3] = 0; /* only first 3 chars significant */ fname[ 3] = 0 ; /* only first 3 chars significant */
mklower(fname); /* and let it be upper or lower case */ mklower( fname) ; /* and let it be upper or lower case */
fnum = ARRAY_SIZE( funcs) ; unsigned fnum = ARRAY_SIZE( funcs) ; /* index to function to eval */
low = 0 ; int low = 0 ; /* binary search low bound */
high = fnum - 1 ; int high = fnum - 1 ; /* binary search high bound */
do { do {
int s, cur ; int s, cur ;
@ -340,92 +337,70 @@ static const char *gtfun( char *fname) {
low = cur + 1 ; low = cur + 1 ;
} while( low <= high) ; } while( low <= high) ;
/* return errorm on a bad reference */ /* return errorm on a bad reference */
if (fnum == ARRAY_SIZE(funcs)) if( fnum == ARRAY_SIZE( funcs))
return errorm; return errorm ;
arg1 = arg2 = arg3 = NULL ; /* fetch arguments */
assert( clexec == TRUE) ; /* means macarg can be replaced by gettokval */ assert( clexec == TRUE) ; /* means macarg can be replaced by gettokval */
/* if needed, retrieve the first argument */ int argc = ARGCOUNT( funcs[ fnum].f_type) ;
if (funcs[fnum].f_type >= MONAMIC) { for( int i = 0 ; i < argc ; i++) {
arg1 = getnewtokval() ; argv[ i] = getnewtokval() ;
if( arg1 == NULL) if( argv[ i] == NULL) {
return errorm; while( i > 0)
free( argv[ --i]) ;
/* if needed, retrieve the second argument */ return errorm ;
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;
}
}
} }
} }
/* and now evaluate it! */ /* and now evaluate it! */
switch( funcs[ fnum].f_type) { switch( FUNID( funcs[ fnum].f_type)) {
int sz ; int sz, sz1 ;
unicode_t c ;
case UFADD | DYNAMIC: case UFADD:
retstr = i_to_a( atoi( arg1) + atoi( arg2)) ; retstr = i_to_a( atoi( argv[ 0]) + atoi( argv[ 1])) ;
break ; break ;
case UFSUB | DYNAMIC: case UFSUB:
retstr = i_to_a( atoi( arg1) - atoi( arg2)) ; retstr = i_to_a( atoi( argv[ 0]) - atoi( argv[ 1])) ;
break ; break ;
case UFTIMES | DYNAMIC: case UFTIMES:
retstr = i_to_a( atoi( arg1) * atoi( arg2)) ; retstr = i_to_a( atoi( argv[ 0]) * atoi( argv[ 1])) ;
break ; break ;
case UFDIV | DYNAMIC: case UFDIV:
sz = atoi( arg2) ; sz = atoi( argv[ 1]) ;
retstr = (sz == 0) ? errorm : i_to_a( atoi( arg1) / sz) ; retstr = (sz == 0) ? errorm : i_to_a( atoi( argv[ 0]) / sz) ;
break ; break ;
case UFMOD | DYNAMIC: case UFMOD:
sz = atoi( arg2) ; sz = atoi( argv[ 1]) ;
retstr = (sz == 0) ? errorm : i_to_a( atoi( arg1) % sz) ; retstr = (sz == 0) ? errorm : i_to_a( atoi( argv[ 0]) % sz) ;
break ; break ;
case UFNEG | MONAMIC: case UFNEG:
retstr = i_to_a( -atoi( arg1)) ; retstr = i_to_a( -atoi( argv[ 0])) ;
break ; break ;
case UFCAT | DYNAMIC: { case UFCAT:
int sz1 ; sz1 = strlen( argv[ 0]) ;
sz = sz1 + strlen( argv[ 1]) + 1 ;
sz1 = strlen( arg1) ;
sz = sz1 + strlen( arg2) + 1 ;
if( sz > ressize) { if( sz > ressize) {
free( result) ; free( result) ;
result = malloc( sz) ; result = malloc( sz) ;
ressize = sz ; ressize = sz ;
} }
strcpy( result, arg1) ; strcpy( result, argv[ 0]) ;
strcpy( &result[ sz1], arg2) ; strcpy( &result[ sz1], argv[ 1]) ;
retstr = result ; retstr = result ;
}
break ; break ;
case UFLEFT | DYNAMIC: { case UFLEFT:
int sz1, i ; sz1 = strlen( argv[ 0]) ;
sz1 = strlen( arg1) ;
sz = 0 ; sz = 0 ;
for( i = atoi( arg2) ; i > 0 ; i -= 1) { for( int i = atoi( argv[ 1]) ; i > 0 ; i -= 1) {
unicode_t c ; unicode_t c ;
int bytc ;
bytc = utf8_to_unicode( arg1, sz, sz1, &c) ; sz += utf8_to_unicode( argv[ 0], sz, sz1, &c) ;
if( bytc == 0) if( sz == sz1)
break ; break ;
else
sz += bytc ;
} }
if( sz >= ressize) { if( sz >= ressize) {
@ -434,41 +409,40 @@ static const char *gtfun( char *fname) {
ressize = sz + 1 ; ressize = sz + 1 ;
} }
mystrscpy( result, arg1, sz + 1) ; mystrscpy( result, argv[ 0], sz + 1) ;
retstr = result ; retstr = result ;
}
break ; break ;
case UFRIGHT | DYNAMIC: case UFRIGHT:
sz = atoi( arg2) ; 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) { if( sz >= ressize) {
free( result) ; free( result) ;
result = malloc( sz + 1) ;
ressize = 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) ; retstr = strcpy( result, retstr) ;
start = 0 ; break ;
for( i = atoi( arg2) - 1 ; i > 0 ; i -= 1) { case UFMID:
bytc = utf8_to_unicode( arg1, start, sz1, &c) ; sz1 = strlen( argv[ 0]) ;
if( bytc == 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 ; break ;
else
start += bytc ;
} }
sz = start ; sz = start ;
for( i = atoi( arg3) ; i > 0 ; i -= 1) { if( sz < sz1)
bytc = utf8_to_unicode( arg1, sz, sz1, &c) ; for( i = atoi( argv[ 2]) ; i > 0 ; i -= 1) {
if( bytc == 0) sz += utf8_to_unicode( argv[ 0], sz, sz1, &c) ;
if( sz == sz1)
break ; break ;
else
sz += bytc ;
} }
sz -= start ; sz -= start ;
@ -478,33 +452,32 @@ static const char *gtfun( char *fname) {
ressize = sz + 1 ; ressize = sz + 1 ;
} }
mystrscpy( result, &arg1[ start], sz + 1) ; mystrscpy( result, &(argv[ 0][ start]), sz + 1) ;
retstr = result ; retstr = result ;
}
break ; break ;
case UFNOT | MONAMIC: case UFNOT:
retstr = ltos( stol( arg1) == FALSE) ; retstr = ltos( stol( argv[ 0]) == FALSE) ;
break ; break ;
case UFEQUAL | DYNAMIC: case UFEQUAL:
retstr = ltos( atoi( arg1) == atoi( arg2)) ; retstr = ltos( atoi( argv[ 0]) == atoi( argv[ 1])) ;
break ; break ;
case UFLESS | DYNAMIC: case UFLESS:
retstr = ltos( atoi( arg1) < atoi( arg2)) ; retstr = ltos( atoi( argv[ 0]) < atoi( argv[ 1])) ;
break ; break ;
case UFGREATER | DYNAMIC: case UFGREATER:
retstr = ltos( atoi( arg1) > atoi( arg2)) ; retstr = ltos( atoi( argv[ 0]) > atoi( argv[ 1])) ;
break ; break ;
case UFSEQUAL | DYNAMIC: case UFSEQUAL:
retstr = ltos( strcmp( arg1, arg2) == 0) ; retstr = ltos( strcmp( argv[ 0], argv[ 1]) == 0) ;
break ; break ;
case UFSLESS | DYNAMIC: case UFSLESS:
retstr = ltos( strcmp( arg1, arg2) < 0) ; retstr = ltos( strcmp( argv[ 0], argv[ 1]) < 0) ;
break ; break ;
case UFSGREAT | DYNAMIC: case UFSGREAT:
retstr = ltos( strcmp( arg1, arg2) > 0) ; retstr = ltos( strcmp( argv[ 0], argv[ 1]) > 0) ;
break ; break ;
case UFIND | MONAMIC: case UFIND:
retstr = getval( arg1) ; retstr = getval( argv[ 0]) ;
sz = strlen( retstr) + 1 ; sz = strlen( retstr) + 1 ;
if( sz > ressize) { if( sz > ressize) {
free( result) ; free( result) ;
@ -514,123 +487,109 @@ static const char *gtfun( char *fname) {
retstr = strcpy( result, retstr) ; retstr = strcpy( result, retstr) ;
break ; break ;
case UFAND | DYNAMIC: case UFAND:
retstr = ltos( stol( arg1) && stol( arg2)) ; retstr = ltos( stol( argv[ 0]) && stol( argv[ 1])) ;
break ; break ;
case UFOR | DYNAMIC: case UFOR:
retstr = ltos( stol( arg1) || stol( arg2)) ; retstr = ltos( stol( argv[ 0]) || stol( argv[ 1])) ;
break ; break ;
case UFLENGTH | MONAMIC: case UFLENGTH:
retstr = i_to_a( strlen( arg1)) ; retstr = i_to_a( strlen( argv[ 0])) ;
break ; break ;
case UFUPPER | MONAMIC: case UFUPPER:
sz = strlen( arg1) ; sz = strlen( argv[ 0]) ;
if( sz >= ressize) { if( sz >= ressize) {
free( result) ; free( result) ;
result = malloc( sz + 1) ; result = malloc( sz + 1) ;
ressize = sz + 1 ; ressize = sz + 1 ;
} }
retstr = mkupper( result, arg1) ; retstr = mkupper( result, argv[ 0]) ;
break ; break ;
case UFLOWER | MONAMIC: case UFLOWER:
sz = strlen( arg1) ; sz = strlen( argv[ 0]) ;
if( sz >= ressize) { if( sz >= ressize) {
free( result) ; free( result) ;
result = malloc( sz + 1) ; result = malloc( sz + 1) ;
ressize = 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) ; retstr = mklower( result) ;
break ; break ;
case UFTRUTH | MONAMIC: case UFTRUTH:
retstr = ltos( atoi( arg1) == 42) ; retstr = ltos( atoi( argv[ 0]) == 42) ;
break ; break ;
case UFASCII | MONAMIC: { case UFASCII:
unicode_t c ; utf8_to_unicode( argv[ 0], 0, 4, &c) ;
utf8_to_unicode( arg1, 0, 4, &c) ;
retstr = i_to_a( 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 ; break ;
case UFCHR | MONAMIC: { case UFGTKEY:
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:
result[0] = tgetc(); result[0] = tgetc();
result[1] = 0; result[1] = 0;
retstr = result ; retstr = result ;
break ; break ;
case UFRND | MONAMIC: case UFRND:
retstr = i_to_a( ernd( atoi( arg1))) ; retstr = i_to_a( ernd( atoi( argv[ 0]))) ;
break ; break ;
case UFABS | MONAMIC: case UFABS:
retstr = i_to_a( abs( atoi( arg1))) ; retstr = i_to_a( abs( atoi( argv[ 0]))) ;
break ; break ;
case UFSINDEX | DYNAMIC: case UFSINDEX:
retstr = i_to_a( sindex( arg1, arg2)) ; retstr = i_to_a( sindex( argv[ 0], argv[ 1])) ;
break ; break ;
case UFENV | MONAMIC: case UFENV:
#if ENVFUNC #if ENVFUNC
retstr = getenv( arg1) ; retstr = getenv( argv[ 0]) ;
if( retstr == NULL) if( retstr == NULL)
retstr = "" ;
#else
retstr = "" ;
#endif #endif
retstr = "" ;
break ; break ;
case UFBIND | MONAMIC: case UFBIND:
retstr = transbind( arg1) ; retstr = transbind( argv[ 0]) ;
break ; break ;
case UFEXIST | MONAMIC: case UFEXIST:
retstr = ltos( fexist( arg1)) ; retstr = ltos( fexist( argv[ 0])) ;
break ; break ;
case UFFIND | MONAMIC: case UFFIND:
retstr = flook( arg1, TRUE) ; retstr = flook( argv[ 0], TRUE) ;
if( retstr == NULL) if( retstr == NULL)
retstr = "" ; retstr = "" ;
break ; break ;
case UFBAND | DYNAMIC: case UFBAND:
retstr = i_to_a( atoi( arg1) & atoi( arg2)) ; retstr = i_to_a( atoi( argv[ 0]) & atoi( argv[ 1])) ;
break ; break ;
case UFBOR | DYNAMIC: case UFBOR:
retstr = i_to_a( atoi( arg1) | atoi( arg2)) ; retstr = i_to_a( atoi( argv[ 0]) | atoi( argv[ 1])) ;
break ; break ;
case UFBXOR | DYNAMIC: case UFBXOR:
retstr = i_to_a( atoi( arg1) ^ atoi( arg2)) ; retstr = i_to_a( atoi( argv[ 0]) ^ atoi( argv[ 1])) ;
break ; break ;
case UFBNOT | MONAMIC: case UFBNOT:
retstr = i_to_a( ~atoi( arg1)) ; retstr = i_to_a( ~atoi( argv[ 0])) ;
break ; break ;
case UFXLATE | TRINAMIC: case UFXLATE:
retstr = xlat( arg1, arg2, arg3) ; retstr = xlat( argv[ 0], argv[ 1], argv[ 2]) ;
break ; break ;
default: default:
assert( FALSE) ; /* never should get here */ assert( FALSE) ; /* never should get here */
retstr = errorm ; retstr = errorm ;
} }
if( arg3) while( argc > 0)
free( arg3) ; free( argv[ --argc]) ;
if( arg2)
free( arg2) ;
if( arg1)
free( arg1) ;
return retstr ; return retstr ;
} }
@ -656,33 +615,55 @@ static char *gtusr( char *vname) {
return errorm; 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 * 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 */ unsigned vnum ; /* ordinal number of var referenced */
/* scan the list, looking for the referenced name */ /* scan the list, looking for the referenced name */
for (vnum = 0; vnum < ARRAY_SIZE(envars); vnum++) for( vnum = 0 ; vnum < ARRAY_SIZE( envars) ; vnum++)
if (strcmp(vname, envars[vnum]) == 0) if( strcmp( vname, envars[ vnum]) == 0)
break; break ;
/* return errorm on a bad reference */ /* return errorm on a bad reference */
if (vnum == ARRAY_SIZE(envars)) if( vnum == ARRAY_SIZE( envars)) {
#if ENVFUNC #if ENVFUNC
{
char *ename = getenv(vname); char *ename = getenv(vname);
if (ename != NULL) if( ename != NULL)
return ename; return ename ;
else
return errorm;
}
#else
return errorm;
#endif #endif
return errorm ;
}
/* otherwise, fetch the appropriate value */ /* otherwise, fetch the appropriate value */
switch (vnum) { switch (vnum) {
@ -778,6 +759,8 @@ static char *gtenv( char *vname) {
return i_to_a( tabwidth) ; return i_to_a( tabwidth) ;
case EVHARDTAB: case EVHARDTAB:
return ltos( hardtab) ; return ltos( hardtab) ;
case EVVIEWTAB:
return ltos( viewtab) ;
case EVOVERLAP: case EVOVERLAP:
return i_to_a(overlap); return i_to_a(overlap);
case EVSCROLLCOUNT: case EVSCROLLCOUNT:
@ -803,7 +786,7 @@ static char *gtenv( char *vname) {
*/ */
BINDABLE( setvar) { BINDABLE( setvar) {
int status; /* status return */ 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 var[NVSIZE + 2]; /* name of variable to fetch %1234567890\0 */
char *value ; /* value to set variable to */ char *value ; /* value to set variable to */
@ -891,7 +874,7 @@ int mdbugout( char *fmt, ...) {
* @vd: structure to hold type and pointer. * @vd: structure to hold type and pointer.
* @size: size of variable array. * @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 */ unsigned vnum = 0 ; /* subscript in variable arrays */
int vtype; /* type to return */ int vtype; /* type to return */
@ -947,7 +930,7 @@ fvar:
* @var: variable to set. * @var: variable to set.
* @value: value to set to. * @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 vnum; /* ordinal number of var refrenced */
int vtype; /* type of variable to set */ int vtype; /* type of variable to set */
@ -1100,6 +1083,9 @@ static int svar(struct variable_description *var, char *value)
case EVHARDTAB: case EVHARDTAB:
hardtab = stol( value) ; hardtab = stol( value) ;
break ; break ;
case EVVIEWTAB:
viewtab = stol( value) ;
break ;
case EVOVERLAP: case EVOVERLAP:
overlap = atoi(value); overlap = atoi(value);
break; break;
@ -1125,7 +1111,7 @@ static int svar(struct variable_description *var, char *value)
* *
* int i; integer to translate to a string * 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 ; unsigned u ;
int sign ; /* sign of resulting number */ int sign ; /* sign of resulting number */
/* returns result string: sign digits null */ /* returns result string: sign digits null */
@ -1151,116 +1137,103 @@ static char *i_to_a( int i) {
return sp ; 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) { static int gettyp( char c) {
char c; /* first char in token */ switch( c) {
case '*':
/* grab the first char (this is all we need) */ case ':':
c = *token; return TKLBL ;
switch (c) {
case 0: /* no blanks!!! */ case 0: /* no blanks!!! */
return TKNUL ; return TKNUL ;
case '"': case '"':
return TKSTR; return TKSTR ;
case '!': case '!':
return TKDIR; return TKDIR ;
case '@': case '@':
return TKARG; return TKARG ;
case '=': case '=':
return TKBUF; return TKBUF ;
case '$': case '$':
return TKENV; return TKENV ;
case '%': case '%':
return TKVAR; return TKVAR ;
case '&': case '&':
return TKFUN; return TKFUN ;
case '*':
return TKLBL;
default: default:
/* a numeric literal? */ /* a numeric literal? */
if( (c >= '0' && c <= '9') || c == '-') if( (c >= '0' && c <= '9') || c == '-')
return TKLIT; return TKLIT ;
else else
return TKCMD; return TKCMD ;
} }
} }
int is_it_cmd( char *token) { 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 * char *token; token to evaluate
*/ */
const char *getval(char *token) const char *getval( char *token) {
{ static char buf[ NSTRING] ; /* string buffer for some returns */
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 "";
switch( gettyp( *token)) {
case TKARG: /* interactive argument */ case TKARG: /* interactive argument */
strcpy(token, getval(&token[1])); strcpy( token, getval( &token[ 1])) ;
distmp = discmd; /* echo it always! */ int distmp = discmd ; /* echo it always! */
discmd = TRUE; discmd = TRUE ;
status = getstring( token, buf, NSTRING, nlc) ; int status = getstring( token, buf, NSTRING, nlc) ;
discmd = distmp; discmd = distmp ;
if (status == ABORT) if (status == ABORT)
return errorm; return errorm ;
return buf;
return buf ;
case TKBUF: /* buffer contents fetch */ case TKBUF: /* buffer contents fetch */
/* grab the right buffer */
/* grab the right buffer */ strcpy( token, getval( &token[ 1])) ;
strcpy(token, getval(&token[1])); buffer_p bp = bfind( token, FALSE, 0) ;
bp = bfind(token, FALSE, 0);
if (bp == NULL) if (bp == NULL)
return errorm; return errorm ;
/* if the buffer is displayed, get the window /* if the buffer is displayed,
vars instead of the buffer vars */ get the window vars instead of the buffer vars */
if (bp->b_nwnd > 0) { if (bp->b_nwnd > 0) {
curbp->b_dotp = curwp->w_dotp; curbp->b_dotp = curwp->w_dotp;
curbp->b_doto = curwp->w_doto; 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) if (bp->b_linep == bp->b_dotp)
return errorm; return errorm;
/* grab the line as an argument */ /* grab the line as an argument */
blen = bp->b_dotp->l_used - bp->b_doto; unsigned blen = bp->b_dotp->l_used - bp->b_doto;
if( blen >= sizeof buf) if( blen >= sizeof buf)
blen = sizeof buf - 1 ; blen = sizeof buf - 1 ;
mystrscpy( buf, bp->b_dotp->l_text + bp->b_doto, blen + 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_dotp = bp->b_dotp->l_fp;
bp->b_doto = 0; bp->b_doto = 0;
/* if displayed buffer, reset window ptr vars */ /* if displayed buffer, reset window ptr vars */
if (bp->b_nwnd > 0) { if (bp->b_nwnd > 0) {
curwp->w_dotp = curbp->b_dotp; curwp->w_dotp = curbp->b_dotp;
curwp->w_doto = 0; curwp->w_doto = 0;
curwp->w_flag |= WFMOVE; curwp->w_flag |= WFMOVE;
} }
/* and return the spoils */ /* and return the spoils */
return buf; return buf;
case TKVAR: case TKVAR:
@ -1269,18 +1242,19 @@ const char *getval(char *token)
return gtenv(token + 1); return gtenv(token + 1);
case TKFUN: case TKFUN:
return gtfun(token + 1); return gtfun(token + 1);
case TKDIR:
return errorm;
case TKLBL:
return errorm;
case TKLIT: case TKLIT:
return token; return token;
case TKSTR: case TKSTR:
return token + 1; return token + 1;
case TKCMD: case TKCMD:
return token; 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 ; return (i <= 0) ? s : s % i + 1 ;
} }
/*
* find pattern within source /* find pattern within source
* *
* char *source; source string to search * char *source; source string to search
* char *pattern; string to look for * char *pattern; string to look for
*/ */
static int sindex( char *source, char *pattern) { static int sindex( char *source, char *pattern) {
char *sp; /* ptr to current position to scan */ /* scanning through the source string */
char *sp = source ; /* ptr to current position to scan */
/* scanning through the source string */
sp = source;
int idx = 1 ; int idx = 1 ;
int pos = 0 ; int pos = 0 ;
int len = strlen( source) ; int len = strlen( source) ;
while (*sp) { while( *sp) {
char *csp; /* ptr to source string during comparison */
char *cp; /* ptr to place to check for equality */
char c ; char c ;
unicode_t uc ; unicode_t uc ;
/* scan through the pattern */ /* scan through the pattern */
cp = pattern; char *cp = pattern ; /* ptr to place to check for equality */
csp = sp; char *csp = sp ; /* ptr to source string during comparison */
while( (c = *cp++) && eq( c, *csp)) while( (c = *cp++) && eq( c, *csp))
csp++ ; csp++ ;
@ -1406,7 +1376,7 @@ static int sindex( char *source, char *pattern) {
} }
/* no match at all.. */ /* no match at all.. */
return 0; return 0 ;
} }
/* /*

2
eval.h
View File

@ -12,7 +12,7 @@
extern int macbug ; /* macro debuging flag */ extern int macbug ; /* macro debuging flag */
extern int cmdstatus ; /* last command status */ extern int cmdstatus ; /* last command status */
extern int rval ; /* return value of a subprocess */ 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 readfirst_f( void) ;
int is_it_cmd( char *token) ; int is_it_cmd( char *token) ;

933
exec.c

File diff suppressed because it is too large Load Diff

14
exec.h
View File

@ -12,13 +12,13 @@ boolean gettokval( char *tok, int maxtoksize) ;
char *getnewtokval( void) ; char *getnewtokval( void) ;
/* Bindable functions */ /* Bindable functions */
BINDABLE( execbuf) ; BINDABLE( execbuf) ;
BINDABLE( execcmd) ; BINDABLE( execcmd) ;
BINDABLE( execfile) ; BINDABLE( execfile) ;
BINDABLE( execproc) ; BINDABLE( execproc) ;
BINDABLE( namedcmd) ; BINDABLE( namedcmd) ;
BINDABLE( storemac) ; BBINDABLE( storemac) ;
BINDABLE( storeproc) ; BINDABLE( storeproc) ;
BINDABLE( cbuf1) ; BINDABLE( cbuf1) ;
BINDABLE( cbuf2) ; BINDABLE( cbuf2) ;
BINDABLE( cbuf3) ; BINDABLE( cbuf3) ;

View File

@ -7,12 +7,12 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include "estruct.h" #include "defines.h"
#include "random.h"
#include "display.h" #include "display.h"
#include "file.h" #include "file.h"
#include "input.h" #include "input.h"
#include "mlout.h" #include "mlout.h"
#include "random.h"
#include "search.h" #include "search.h"
#include "terminal.h" #include "terminal.h"
#include "window.h" #include "window.h"
@ -55,10 +55,7 @@ static int inspound( int n) {
static int insbrace( int n, int c) { static int insbrace( int n, int c) {
int ch ; /* last character before input */ int ch ; /* last character before input */
int oc ; /* caractere oppose a c */ int oc ; /* caractere oppose a c */
int i, count ;
int target ; /* column brace should go after */ int target ; /* column brace should go after */
struct line *oldlp ;
int oldoff ;
/* if not called with {, acts as insertion */ /* if not called with {, acts as insertion */
if( c == '}') if( c == '}')
@ -67,16 +64,17 @@ static int insbrace( int n, int c) {
return linsert( n, c) ; return linsert( n, c) ;
/* scan to see if all preceding spaces are white spaces, if not, insert */ /* 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) ; ch = lgetc( curwp->w_dotp, i) ;
if( ch != ' ' && ch != '\t') if( ch != ' ' && ch != '\t')
return linsert( n, c) ; return linsert( n, c) ;
} }
oldlp = curwp->w_dotp ; /* save the original cursor position */
oldoff = curwp->w_doto ; line_p oldlp = curwp->w_dotp ;
int oldoff = curwp->w_doto ;
count = 1 ; int count = 1 ;
do { do {
if( boundary( curwp->w_dotp, curwp->w_doto, REVERSE)) { if( boundary( curwp->w_dotp, curwp->w_doto, REVERSE)) {
/* at beginning of buffer, no match to be found */ /* 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 * char ch; fence type to match against
*/ */
static void fmatch( int ch) { 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 */ int opench ; /* open fence */
/* $tpause <= 0 disable fmatch */ /* $tpause <= 0 disable fmatch */
@ -146,8 +140,8 @@ static void fmatch( int ch) {
update( FALSE) ; update( FALSE) ;
/* save the original cursor position */ /* save the original cursor position */
oldlp = curwp->w_dotp ; line_p oldlp = curwp->w_dotp ;
oldoff = curwp->w_doto ; int oldoff = curwp->w_doto ;
/* setup proper open fence for passed close fence */ /* setup proper open fence for passed close fence */
if( ch == ')') if( ch == ')')
@ -158,11 +152,11 @@ static void fmatch( int ch) {
opench = '[' ; opench = '[' ;
/* find the top line and set up for scan */ /* 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 */ backchar( FALSE, 1) ; /* . was after the }, move back */
/* scan back until we find it, or reach past the top of the window */ /* scan back until we find it, or reach past the top of the window */
count = 1 ; int count = 1 ; /* current fence level count */
do { do {
/* At beginning of window or buffer, no match to be found */ /* At beginning of window or buffer, no match to be found */
if( curwp->w_dotp == toplp if( curwp->w_dotp == toplp
@ -209,17 +203,14 @@ static void fmatch( int ch) {
* int f, n; not used * int f, n; not used
*/ */
BINDABLE( getfence) { BINDABLE( getfence) {
struct line *oldlp; /* original line pointer */
int oldoff; /* and offset */
int sdir; /* direction of search (1/-1) */ int sdir; /* direction of search (1/-1) */
int count; /* current fence level count */
char ch; /* fence type to match against */ char ch; /* fence type to match against */
char ofence; /* open fence */ char ofence; /* open fence */
char c; /* current character in scan */ char c; /* current character in scan */
/* save the original cursor position */ /* save the original cursor position */
oldlp = curwp->w_dotp; line_p oldlp = curwp->w_dotp ;
oldoff = curwp->w_doto; int oldoff = curwp->w_doto ;
/* get the current character */ /* get the current character */
if (oldoff == llength(oldlp)) if (oldoff == llength(oldlp))
@ -259,7 +250,7 @@ BINDABLE( getfence) {
} }
/* scan until we find a match, or reach the end of file */ /* scan until we find a match, or reach the end of file */
count = 1 ; int count = 1 ; /* current fence level count */
do { do {
if( boundary( curwp->w_dotp, curwp->w_doto, sdir)) { if( boundary( curwp->w_dotp, curwp->w_doto, sdir)) {
/* at buffer limit, no match to be found */ /* at buffer limit, no match to be found */

1
file.c
View File

@ -17,7 +17,6 @@
#include "buffer.h" #include "buffer.h"
#include "defines.h" #include "defines.h"
#include "display.h" #include "display.h"
#include "estruct.h"
#include "execute.h" #include "execute.h"
#include "fileio.h" #include "fileio.h"
#include "input.h" #include "input.h"

View File

@ -1,35 +1,16 @@
## floodmaz.cmd -- solve maze by painting wall on the right
# 6 set $seed # 6 set $seed
execute-file maze.cmd # either maze.cmd or sharpmaz.cmd
execute-file sharpmaz.cmd
set %thisbuf $cbufname set %thisbuf $cbufname
set %meml $curline
store-procedure pushxy # push x y set %memc $curcol
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 $curline 1 set $curline 1
set $curcol 0 set $curcol 0
run pushxy #push stop position !gosub pushxy #push stop position
set %x 1 set %x 1
set $curline 4 set $curline 4
set $curcol %x set $curcol %x
@ -40,29 +21,47 @@ set %NC &asc "█"
set %cc $curcol set %cc $curcol
set %ll $curline set %ll $curline
set $curcol &add %cc 1 set $curcol &add %cc 1
!if &equ $curchar %OC !gosub probe
run pushxy
!endif
set $curcol &add %cc -1 set $curcol &add %cc -1
!if &equ $curchar %OC !gosub probe
run pushxy
!endif
set $curline &add %ll 1 set $curline &add %ll 1
set $curcol %cc set $curcol %cc
!if &equ $curchar %OC !gosub probe
run pushxy
!endif
set $curline &add %ll -1 set $curline &add %ll -1
set $curcol %cc set $curcol %cc
!if &equ $curchar %OC !gosub probe
run pushxy # pop x y
!endif select-buffer stack
run popxy 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 !endwhile
set $curline 3
set $curcol 1 set $curline %meml
set $curcol %memc
select-buffer stack select-buffer stack
unmark-buffer unmark-buffer
select-buffer %thisbuf select-buffer %thisbuf
unmark-buffer unmark-buffer
delete-buffer stack delete-buffer stack
!return
:probe
!if &not &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

View File

@ -13,8 +13,8 @@
#include <unistd.h> #include <unistd.h>
#include "bind.h" #include "bind.h"
#include "estruct.h"
#include "bindable.h" #include "bindable.h"
#include "defines.h"
#include "display.h" /* rubout(), echos(), echoc(), update() */ #include "display.h" /* rubout(), echos(), echoc(), update() */
#include "exec.h" #include "exec.h"
#include "isa.h" #include "isa.h"

View File

@ -27,8 +27,8 @@
#include "basic.h" #include "basic.h"
#include "buffer.h" #include "buffer.h"
#include "defines.h"
#include "display.h" #include "display.h"
#include "estruct.h"
#include "exec.h" #include "exec.h"
#include "input.h" #include "input.h"
#include "line.h" #include "line.h"

758
line.c
View File

@ -20,7 +20,8 @@
#include <string.h> #include <string.h>
#include "buffer.h" #include "buffer.h"
#include "estruct.h" #include "defines.h"
#include "list.h"
#include "mlout.h" #include "mlout.h"
#include "utf8.h" #include "utf8.h"
#include "window.h" #include "window.h"
@ -37,58 +38,46 @@ static int ldelnewline( void) ;
* was taken up by the keycode structure). * was taken up by the keycode structure).
*/ */
#define KBLOCK 250 /* sizeof kill buffer chunks */ #define KBLOCK 248 /* sizeof kill buffer chunks */
typedef struct kill { typedef struct kill {
struct kill *d_next; /* Link to next chunk, NULL if last. */ struct kill *d_next ; /* Link to next chunk, NULL if last. */
char d_chunk[KBLOCK]; /* Deleted text. */ char d_chunk[ KBLOCK] ; /* Deleted text. */
} *kill_p ; } *kill_p ;
static kill_p kbufp = NULL ; /* current kill buffer chunk pointer */ static kill_p kbufp = NULL ; /* current kill buffer chunk pointer */
static kill_p kbufh = NULL ; /* kill buffer header pointer */ static kill_p kbufh = NULL ; /* kill buffer header pointer */
static int kused = KBLOCK ; /* # of bytes used in kill buffer */ static int kused = KBLOCK ; /* # of bytes used in kill buffer */
static int klen ; /* length of kill buffer content */ static int klen ; /* length of kill buffer content */
static char *value = NULL ; /* temp buffer for value */ static char *value = NULL ; /* temp buffer for value */
/* /*
* return some of the contents of the kill buffer * return some of the contents of the kill buffer
*/ */
char *getkill( void) { const char *getkill( void) {
kill_p kp ; /* no kill buffer or no memory .... just return a null string */
char *cp ; if( kbufh == NULL
|| (value = realloc( value, klen + 1)) == NULL)
if (kbufh == NULL)
/* no kill buffer....just a null string */
return "" ; return "" ;
if( value != NULL) char *cp = value ;
free( value) ; for( kill_p kp = kbufh ; kp != NULL ; kp = kp->d_next) {
int size = (kp->d_next != NULL) ? KBLOCK : kused ;
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 ;
memcpy( cp, kp->d_chunk, size) ; memcpy( cp, kp->d_chunk, size) ;
cp += size ; cp += size ;
} }
*cp = 0 ; *cp = 0 ;
/* and return the constructed value */ /* and return the constructed value */
return value; return value ;
} }
/* Move the cursor backwards by "n" characters. If "n" is less than zero /* Move the cursor backwards by "n" combined characters. If "n" is less
call "forwchar" to actually do the move. Otherwise compute the new than zero call "forwchar" to actually do the move. Otherwise compute
cursor location. Error if you try and move out of the buffer. Set the the new cursor location. Error if you try and move out of the buffer.
flag if the line pointer for dot changes. Set the flag if the line pointer for dot changes.
*/ */
BBINDABLE( backchar) { BBINDABLE( backchar) {
assert( f == TRUE || n == 1) ; assert( f == TRUE || n == 1) ;
@ -105,9 +94,26 @@ BBINDABLE( backchar) {
curwp->w_doto = llength( lp) ; curwp->w_doto = llength( lp) ;
curwp->w_flag |= WFMOVE ; curwp->w_flag |= WFMOVE ;
} else { } else {
unsigned pos = curwp->w_doto -= 1 ; unsigned pos ;
if( pos > 0) /* move back over combining unicode */
curwp->w_doto -= utf8_revdelta( (unsigned char *) &( (curwp->w_dotp)->l_text[ pos]), pos) ; 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 /* Move the cursor forwards by "n" combined characters. If "n" is less
call "backchar" to actually do the move. Otherwise compute the new than zero call "backchar" to actually do the move. Otherwise compute
cursor location, and move ".". Error if you try and move off the end of the new cursor location, and move ".". Error if you try and move off
the buffer. Set the flag if the line pointer for dot changes. the end of the buffer. Set the flag if the line pointer for dot
changes.
*/ */
BBINDABLE( forwchar) { BBINDABLE( forwchar) {
assert( f == TRUE || n == 1) ; 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 += utf8_to_unicode( curwp->w_dotp->l_text,
curwp->w_doto, len, &unc) ; curwp->w_doto, len, &unc) ;
/* check if next char is null width unicode */ /* 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, unsigned bytes = utf8_to_unicode( curwp->w_dotp->l_text,
curwp->w_doto, len, &unc) ; curwp->w_doto, len, &unc) ;
if( utf8_width( unc) == 0) if( utf8_width( unc) == 0)
@ -154,8 +161,8 @@ BBINDABLE( forwchar) {
return TRUE ; 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 * 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 * 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. * message in the message line if no space.
@ -163,13 +170,13 @@ BBINDABLE( forwchar) {
line_p lalloc( int used) { line_p lalloc( int used) {
#define BLOCK_SIZE 16 /* Line block chunk size. */ #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 #if (BLOCK_SIZE & -BLOCK_SIZE) == BLOCK_SIZE
int size = (used + BLOCK_SIZE) & ~(BLOCK_SIZE - 1) ; int size = (used + BLOCK_SIZE) & ~(BLOCK_SIZE - 1) ;
#else #else
int size = used + BLOCK_SIZE - used % BLOCK_SIZE ; int size = used + BLOCK_SIZE - used % BLOCK_SIZE ;
#endif #endif
line_p lp = (line_p) malloc( offsetof( struct line, l_text) + size) ; line_p lp = malloc( sizeof *lp + size) ;
if( lp == NULL) if( lp == NULL)
mloutstr( "(OUT OF MEMORY)") ; mloutstr( "(OUT OF MEMORY)") ;
else { else {
@ -180,76 +187,70 @@ line_p lalloc( int used) {
return lp ; 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 * 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 * might be in. Release the memory. The buffers are updated too; the magic
* conditions described in the above comments don't hold here. * conditions described in the above comments don't hold here.
*/ */
void lfree( line_p lp) { void lfree( line_p lp) {
buffer_p bp; for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
struct window *wp; if( wp->w_linep == lp)
wp->w_linep = lp->l_fp ;
wp = wheadp; if( wp->w_dotp == lp) {
while (wp != NULL) { wp->w_dotp = lp->l_fp ;
if (wp->w_linep == lp) wp->w_doto = 0 ;
wp->w_linep = lp->l_fp;
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; if( wp->w_markp == lp) {
wp->w_marko = 0; wp->w_markp = lp->l_fp ;
wp->w_marko = 0 ;
} }
wp = wp->w_wndp;
} }
bp = bheadp;
while (bp != NULL) { for( buffer_p bp = bheadp ; bp != NULL ; bp = bp->b_bufp) {
if (bp->b_nwnd == 0) { if( bp->b_nwnd == 0) {
if (bp->b_dotp == lp) { if( bp->b_dotp == lp) {
bp->b_dotp = lp->l_fp; bp->b_dotp = lp->l_fp ;
bp->b_doto = 0; bp->b_doto = 0 ;
} }
if (bp->b_markp == lp) {
bp->b_markp = lp->l_fp; if( bp->b_markp == lp) {
bp->b_marko = 0; 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; lp->l_bp->l_fp = lp->l_fp ;
free((char *) lp); 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 * 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 * 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). * mode line needs to be updated (the "*" has to be set).
*/ */
void lchange(int flag) void lchange( int flag) {
{ if( curbp->b_nwnd != 1) /* Ensure hard. */
struct window *wp; flag = WFHARD ;
if (curbp->b_nwnd != 1) /* Ensure hard. */ if( (curbp->b_flag & BFCHG) == 0) { /* First change, so */
flag = WFHARD; flag |= WFMODE ; /* update mode lines. */
if ((curbp->b_flag & BFCHG) == 0) { /* First change, so */ curbp->b_flag |= BFCHG ;
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;
} }
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 * int f, n; default flag and numeric argument
*/ */
@ -260,24 +261,18 @@ BINDABLE( insspace) {
return TRUE ; 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) { if( instr != NULL) {
unicode_t tmpc ; int c ;
while( (tmpc = *instr++ & 0xFF)) { while( (c = (unsigned char) *instr++)) {
status = status = (c == '\n') ? lnewline() : linsert_byte( 1, c) ;
(tmpc == '\n' ? lnewline() : (int) linsert_byte( 1, tmpc)) ; if( status != TRUE) { /* Insertion error? */
/* Insertion error? */
if( status != TRUE) {
mloutstr( "%Out of memory while inserting") ; mloutstr( "%Out of memory while inserting") ;
return status ; break ;
} }
} }
} }
@ -298,84 +293,88 @@ int linstr( char *instr) {
boolean linsert_byte( int n, int c) { boolean linsert_byte( int n, int c) {
char *cp1; char *cp1;
char *cp2; char *cp2;
line_p lp1, lp2, lp3 ; line_p lp2, lp3 ;
int doto; int i ;
int i;
struct window *wp;
assert( (curbp->b_mode & MDVIEW) == 0) ; assert( (curbp->b_mode & MDVIEW) == 0) ;
lchange(WFEDIT); lchange( WFEDIT) ;
lp1 = curwp->w_dotp; /* Current line */ line_p lp1 = curwp->w_dotp ; /* Current line */
if (lp1 == curbp->b_linep) { /* At the end: special */ if( lp1 == curbp->b_linep) { /* At the end: special */
if (curwp->w_doto != 0) { if( curwp->w_doto != 0)
mloutstr( "bug: linsert") ; return mloutfail( "bug: linsert") ;
return FALSE;
}
lp2 = lalloc( n) ; /* Allocate new line */ lp2 = lalloc( n) ; /* Allocate new line */
if( lp2 == NULL) if( lp2 == NULL)
return FALSE ; return FALSE ;
lp3 = lp1->l_bp; /* Previous line */ lp3 = lp1->l_bp ; /* Previous line */
lp3->l_fp = lp2; /* Link in */ lp3->l_fp = lp2 ; /* Link in */
lp2->l_fp = lp1; lp2->l_fp = lp1 ;
lp1->l_bp = lp2; lp1->l_bp = lp2 ;
lp2->l_bp = lp3; lp2->l_bp = lp3 ;
for (i = 0; i < n; ++i) for( i = 0 ; i < n ; ++i)
lp2->l_text[i] = c; lp2->l_text[ i] = c ;
curwp->w_dotp = lp2;
curwp->w_doto = n; curwp->w_dotp = lp2 ;
return TRUE; 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) ; lp2 = lalloc( lp1->l_used + n) ;
if( lp2 == NULL) if( lp2 == NULL)
return FALSE ; return FALSE ;
cp1 = &lp1->l_text[0]; cp1 = &lp1->l_text[ 0] ;
cp2 = &lp2->l_text[0]; cp2 = &lp2->l_text[ 0] ;
while (cp1 != &lp1->l_text[doto]) while( cp1 != &lp1->l_text[ doto])
*cp2++ = *cp1++; *cp2++ = *cp1++ ;
cp2 += n;
while (cp1 != &lp1->l_text[lp1->l_used]) cp2 += n ;
*cp2++ = *cp1++; while( cp1 != &lp1->l_text[ lp1->l_used])
lp1->l_bp->l_fp = lp2; *cp2++ = *cp1++ ;
lp2->l_fp = lp1->l_fp;
lp1->l_fp->l_bp = lp2; lp1->l_bp->l_fp = lp2 ;
lp2->l_bp = lp1->l_bp; lp2->l_fp = lp1->l_fp ;
free((char *) lp1); lp1->l_fp->l_bp = lp2 ;
lp2->l_bp = lp1->l_bp ;
free( lp1) ;
} else { /* Easy: in place */ } else { /* Easy: in place */
lp2 = lp1; /* Pretend new line */ lp2 = lp1 ; /* Pretend new line */
lp2->l_used += n; lp2->l_used += n ;
cp2 = &lp1->l_text[lp1->l_used]; cp2 = &lp1->l_text[ lp1->l_used] ;
cp1 = cp2 - n; cp1 = cp2 - n ;
while (cp1 != &lp1->l_text[doto]) while( cp1 != &lp1->l_text[ doto])
*--cp2 = *--cp1; *--cp2 = *--cp1 ;
} }
for (i = 0; i < n; ++i) /* Add the characters */
lp2->l_text[doto + i] = c; for( i = 0 ; i < n ; ++i) /* Add the characters */
wp = wheadp; /* Update windows */ lp2->l_text[ doto + i] = c ;
while (wp != NULL) {
if (wp->w_linep == lp1) /* Update windows */
wp->w_linep = lp2; for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
if (wp->w_dotp == lp1) { if( wp->w_linep == lp1)
wp->w_dotp = lp2; wp->w_linep = lp2 ;
if (wp == curwp || wp->w_doto > doto)
wp->w_doto += n; 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_markp == lp1) {
if (wp->w_marko > doto) wp->w_markp = lp2 ;
wp->w_marko += n; 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( n >= 0) ;
assert( !(curbp->b_mode & MDVIEW)) ; assert( !(curbp->b_mode & MDVIEW)) ;
@ -403,7 +402,7 @@ int linsert( int n, unicode_t c) {
* *
* int c ; character to overwrite on current position * 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 if( curwp->w_doto < curwp->w_dotp->l_used
&& ( lgetc( curwp->w_dotp, curwp->w_doto) != '\t' && ( lgetc( curwp->w_dotp, curwp->w_doto) != '\t'
|| (curwp->w_doto % tabwidth) == (tabwidth - 1) || (curwp->w_doto % tabwidth) == (tabwidth - 1)
@ -413,20 +412,18 @@ static int lowrite( int c) {
return linsert( 1, 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) { if( ostr != NULL) {
char tmpc ; int c ;
while( (tmpc = *ostr++)) { while( (c = (unsigned char) *ostr++)) {
status = (tmpc == '\n' ? lnewline() : lowrite( tmpc)) ; status = (c == '\n') ? lnewline() : lowrite( c) ;
if( status != TRUE) { /* Insertion error? */ if( status != TRUE) { /* Insertion error? */
mloutstr( "%Out of memory while overwriting") ; mloutstr( "%Out of memory while overwriting") ;
return status ; break ;
} }
} }
} }
@ -434,21 +431,15 @@ int lover( char *ostr) {
return status ; 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)) ; assert( !(curbp->b_mode & MDVIEW)) ;
#if SCROLLCODE #if SCROLLCODE
@ -456,75 +447,104 @@ int lnewline( void) {
#else #else
lchange(WFHARD); lchange(WFHARD);
#endif #endif
lp1 = curwp->w_dotp; /* Get the address and */ line_p lp1 = curwp->w_dotp ; /* Get the address and */
doto = curwp->w_doto; /* offset of "." */ int doto = curwp->w_doto ; /* offset of "." */
lp2 = lalloc( doto) ; /* New first half line */ line_p lp2 = lalloc( doto) ; /* New first half line */
if( lp2 == NULL) if( lp2 == NULL)
return FALSE ; return FALSE ;
cp1 = &lp1->l_text[0]; /* Shuffle text around */ memcpy( lp2->l_text, lp1->l_text, doto) ;
cp2 = &lp2->l_text[0]; lp1->l_used -= doto ;
while (cp1 != &lp1->l_text[doto]) memcpy( lp1->l_text, &lp1->l_text[ doto], lp1->l_used) ;
*cp2++ = *cp1++; lp2->l_fp = lp1 ;
cp2 = &lp1->l_text[0]; lp2->l_bp = lp1->l_bp ;
while (cp1 != &lp1->l_text[lp1->l_used]) lp1->l_bp = lp2 ;
*cp2++ = *cp1++; lp2->l_bp->l_fp = lp2 ;
lp1->l_used -= doto; for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
lp2->l_bp = lp1->l_bp; if( wp->w_linep == lp1)
lp1->l_bp = lp2; wp->w_linep = lp2 ;
lp2->l_bp->l_fp = lp2;
lp2->l_fp = lp1; if( wp->w_dotp == lp1) {
wp = wheadp; /* Windows */ if( wp->w_doto < doto)
while (wp != NULL) { wp->w_dotp = lp2 ;
if (wp->w_linep == lp1)
wp->w_linep = lp2;
if (wp->w_dotp == lp1) {
if (wp->w_doto < doto)
wp->w_dotp = lp2;
else else
wp->w_doto -= doto; wp->w_doto -= doto ;
} }
if (wp->w_markp == lp1) { if (wp->w_markp == lp1) {
if (wp->w_marko < doto) if( wp->w_marko < doto)
wp->w_markp = lp2; wp->w_markp = lp2 ;
else 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) { /* lgetchar():
*c = (curbp->b_mode & MDDOS) ? '\r' : '\n' ; * 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 ; return 1 ;
} else } else
return utf8_to_unicode( curwp->w_dotp->l_text, curwp->w_doto, 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. * ldelete() really fundamentally works on bytes, not characters.
* It is used for things like "scan 5 words forwards, and remove * It is used for things like "scan 5 words forwards, and remove
* the bytes we scanned". * the bytes we scanned".
* *
* If you want to delete characters, use ldelchar(). * 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() */ /* testing for read only mode is done by ldelete() */
while( n-- > 0) { while( n-- > 0)
unicode_t c; if( !ldelete( lcombinedsize(), kill_f))
if( !ldelete( lgetchar( &c), kflag))
return FALSE ; return FALSE ;
}
return TRUE ; 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 * 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 * 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. * 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 * int kflag; put killed text in kill buffer flag
*/ */
boolean ldelete( long n, boolean kflag) { 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)) ; assert( !(curbp->b_mode & MDVIEW)) ;
while( n > 0) { while( n > 0) {
dotp = curwp->w_dotp; line_p dotp = curwp->w_dotp ;
doto = curwp->w_doto; if( dotp == curbp->b_linep) /* Hit end of buffer. */
if (dotp == curbp->b_linep) /* Hit end of buffer. */ return FALSE ;
return FALSE;
chunk = dotp->l_used - doto; /* Size of chunk. */ int doto = curwp->w_doto ;
if (chunk > n) int chunk = dotp->l_used - doto ; /* Size of chunk. */
chunk = n; if( chunk == 0) { /* End of line, merge. */
if (chunk == 0) { /* End of line, merge. */
#if SCROLLCODE #if SCROLLCODE
lchange(WFHARD | WFKILLS); lchange( WFHARD | WFKILLS) ;
#else #else
lchange(WFHARD); lchange( WFHARD) ;
#endif #endif
if (ldelnewline() == FALSE if( ldelnewline() == FALSE
|| (kflag != FALSE && kinsert('\n') == FALSE)) || (kflag != FALSE && kinsert( '\n') == FALSE))
return 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;
}
/* --n ;
* getctext: grab and return a string with the text of continue ;
* the current line } else if( chunk > n)
*/ chunk = n ;
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 */
/* find the contents of the current line and its length */ lchange( WFEDIT) ;
lp = curwp->w_dotp; char *cp1 = &dotp->l_text[ doto] ; /* Scrunch text. */
size = lp->l_used; char *cp2 = cp1 + chunk ;
if( size >= rsize) { if( kflag != FALSE) { /* Kill? */
if( rsize) while( cp1 != cp2) {
free( rline) ; if( kinsert( *cp1) == FALSE)
return FALSE ;
++cp1 ;
}
rsize = size + 1 ; cp1 = &dotp->l_text[ doto] ;
rline = malloc( rsize) ;
if( rline == NULL) {
rsize = 0 ;
return "" ;
} }
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 */ return TRUE ;
memcpy( rline, lp->l_text, size) ;
rline[ size] = 0 ;
return rline ;
} }
/*
* 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 * 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 * 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 * 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) { static int ldelnewline( void) {
char *cp1; char *cp1;
char *cp2; char *cp2;
line_p lp1, lp2, lp3 ; window_p wp ;
struct window *wp;
assert( (curbp->b_mode & MDVIEW) == 0) ; assert( (curbp->b_mode & MDVIEW) == 0) ;
lp1 = curwp->w_dotp; line_p lp1 = curwp->w_dotp ;
lp2 = lp1->l_fp; line_p lp2 = lp1->l_fp ;
if (lp2 == curbp->b_linep) { /* At the buffer end. */ if( lp2 == curbp->b_linep) { /* At the buffer end. */
if (lp1->l_used == 0) /* Blank line. */ if( lp1->l_used == 0) /* Blank line. */
lfree(lp1); lfree( lp1) ;
return TRUE;
return TRUE ;
} }
if (lp2->l_used <= lp1->l_size - lp1->l_used) {
cp1 = &lp1->l_text[lp1->l_used]; if( lp2->l_used <= lp1->l_size - lp1->l_used) {
cp2 = &lp2->l_text[0]; cp1 = &lp1->l_text[ lp1->l_used] ;
while (cp2 != &lp2->l_text[lp2->l_used]) cp2 = lp2->l_text ;
*cp1++ = *cp2++; while( cp2 != &lp2->l_text[ lp2->l_used])
wp = wheadp; *cp1++ = *cp2++ ;
while (wp != NULL) {
if (wp->w_linep == lp2) for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
wp->w_linep = lp1; if( wp->w_linep == lp2)
if (wp->w_dotp == lp2) { wp->w_linep = lp1 ;
wp->w_dotp = lp1;
wp->w_doto += lp1->l_used; if( wp->w_dotp == lp2) {
wp->w_dotp = lp1 ;
wp->w_doto += lp1->l_used ;
} }
if (wp->w_markp == lp2) {
wp->w_markp = lp1; if( wp->w_markp == lp2) {
wp->w_marko += lp1->l_used; 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; lp1->l_used += lp2->l_used ;
lp2->l_fp->l_bp = lp1; lp1->l_fp = lp2->l_fp ;
free((char *) lp2); lp2->l_fp->l_bp = lp1 ;
return TRUE; 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) if( lp3 == NULL)
return FALSE ; return FALSE ;
cp1 = &lp1->l_text[0]; cp1 = lp1->l_text ;
cp2 = &lp3->l_text[0]; cp2 = lp3->l_text ;
while (cp1 != &lp1->l_text[lp1->l_used]) while( cp1 != &lp1->l_text[ lp1->l_used])
*cp2++ = *cp1++; *cp2++ = *cp1++ ;
cp1 = &lp2->l_text[0];
while (cp1 != &lp2->l_text[lp2->l_used]) cp1 = lp2->l_text ;
*cp2++ = *cp1++; while( cp1 != &lp2->l_text[ lp2->l_used])
lp1->l_bp->l_fp = lp3; *cp2++ = *cp1++ ;
lp3->l_fp = lp2->l_fp;
lp2->l_fp->l_bp = lp3; lp1->l_bp->l_fp = lp3 ;
lp3->l_bp = lp1->l_bp; lp3->l_fp = lp2->l_fp ;
wp = wheadp; lp2->l_fp->l_bp = lp3 ;
while (wp != NULL) { lp3->l_bp = lp1->l_bp ;
if (wp->w_linep == lp1 || wp->w_linep == lp2) for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
wp->w_linep = lp3; if( wp->w_linep == lp1 || wp->w_linep == lp2)
if (wp->w_dotp == lp1) wp->w_linep = lp3 ;
wp->w_dotp = lp3;
else if (wp->w_dotp == lp2) { if( wp->w_dotp == lp1)
wp->w_dotp = lp3; wp->w_dotp = lp3 ;
wp->w_doto += lp1->l_used; 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; if( wp->w_markp == lp1)
else if (wp->w_markp == lp2) { wp->w_markp = lp3 ;
wp->w_markp = lp3; else if( wp->w_markp == lp2) {
wp->w_marko += lp1->l_used; wp->w_markp = lp3 ;
wp->w_marko += lp1->l_used ;
} }
wp = wp->w_wndp;
} }
free((char *) lp1);
free((char *) lp2); free( lp1) ;
return TRUE; 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 * new kill context is being created. The kill buffer array is released, just
* in case the buffer has grown to immense size. No errors. * in case the buffer has grown to immense size. No errors.
*/ */
void kdelete(void) void kdelete( void) {
{ if( kbufh != NULL) {
kill_p kp; /* ptr to scan kill buffer chunk list */ /* first, delete all the chunks */
freelist( (list_p) kbufh) ;
if (kbufh != NULL) { /* and reset all the kill buffer pointers */
kbufh = kbufp = NULL ;
/* first, delete all the chunks */ kused = KBLOCK ;
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;
klen = 0 ; klen = 0 ;
if( value != NULL) { if( value != NULL) {
free( value) ; free( value) ;

26
line.h
View File

@ -14,11 +14,11 @@
list of marks into the line. list of marks into the line.
*/ */
typedef struct line { typedef struct line {
struct line *l_fp ; /* Forward link to the next line */ struct line *l_fp ; /* Forward link to the next line */
struct line *l_bp ; /* Backward link to the previous line */ struct line *l_bp ; /* Backward link to the previous line */
int l_size ; /* Allocated size */ int l_size ; /* Allocated size */
int l_used ; /* Used size */ int l_used ; /* Used size */
char l_text[ 1] ; /* A bunch of characters */ char l_text[] ; /* A bunch of characters */
} *line_p ; } *line_p ;
#define lforw(lp) ((lp)->l_fp) #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, .. */ extern int tabwidth ; /* Map to $tab, default to 8, can be set to [1, .. */
char *getkill( void) ;
/* Bindable functions */ /* Bindable functions */
BBINDABLE( backchar) ; BBINDABLE( backchar) ;
BBINDABLE( forwchar) ; BBINDABLE( forwchar) ;
BINDABLE( insspace) ; BINDABLE( insspace) ;
BINDABLE( yank) ; BINDABLE( yank) ;
void lfree( line_p lp) ;
void lchange( int flag) ; void lchange( int flag) ;
int linstr( char *instr) ; boolean linstr( char *instr) ;
int linsert( int n, unicode_t c) ; boolean linsert( int n, unicode_t c) ;
boolean linsert_byte( int n, int c) ; boolean linsert_byte( int n, int c) ;
int lover( char *ostr) ; boolean lover( char *ostr) ;
int lnewline( void) ; boolean lnewline( void) ;
boolean ldelete( long n, boolean kflag) ; boolean ldelete( long n, boolean kflag) ;
boolean ldelchar( long n, boolean kflag) ; boolean ldelchar( long n, boolean kflag) ;
int lgetchar( unicode_t *cref) ; int lgetchar( unicode_t *cref) ;
char *getctext( void) ;
void kdelete( void) ; void kdelete( void) ;
int kinsert( int c) ; 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 */ boolean rdonly( void) ; /* Read Only error message */

16
list.c Normal file
View File

@ -0,0 +1,16 @@
/* list.c -- implements list.h */
/* Copyright © 2021 Renaud Fivet */
#include "list.h"
#include <stdlib.h> /* free() */
/* free a list */
void freelist( list_p lp) {
while( lp) {
list_p next = lp->next ;
free( lp) ;
lp = next ;
}
}
/* end of list.c */

13
list.h Normal file
View File

@ -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 */

2
lock.h
View File

@ -2,7 +2,7 @@
#ifndef _LOCK_H_ #ifndef _LOCK_H_
#define _LOCK_H_ #define _LOCK_H_
#include "estruct.h" #include "defines.h" /* BSD, SVR4 */
#if BSD | SVR4 #if BSD | SVR4
int lockchk( const char *fname) ; int lockchk( const char *fname) ;

165
main.c
View File

@ -62,14 +62,13 @@
* *
*/ */
#include <locale.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "estruct.h" /* Global structures and defines. */ #include "defines.h" /* OS specific customization */
#if UNIX #if UNIX
#include <signal.h> # include <signal.h>
#endif #endif
#include "basic.h" #include "basic.h"
@ -91,9 +90,8 @@
#include "window.h" #include "window.h"
#if UNIX #if UNIX
static void emergencyexit(int signr) static void emergencyexit( int signr) {
{ quickexit( FALSE, 0) ;
quickexit(FALSE, 0);
quit( TRUE, 0) ; /* If quickexit fails (to save changes), do a force quit */ quit( TRUE, 0) ; /* If quickexit fails (to save changes), do a force quit */
} }
#endif #endif
@ -124,13 +122,12 @@ static void usage( void) {
} }
int main(int argc, char **argv) int main( int argc, char *argv[]) {
{ buffer_p bp; /* temp buffer pointer */
struct buffer *bp; /* temp buffer pointer */
int firstfile; /* first file flag */ int firstfile; /* first file flag */
int carg; /* current arg to scan */ int carg; /* current arg to scan */
int startflag; /* startup executed flag */ 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 viewflag; /* are we starting in view mode? */
int gotoflag; /* do we need to goto a line at start? */ int gotoflag; /* do we need to goto a line at start? */
int gline = 0; /* if so, what line? */ int gline = 0; /* if so, what line? */
@ -138,17 +135,10 @@ int main(int argc, char **argv)
int errflag; /* C error processing? */ int errflag; /* C error processing? */
bname_t bname ; /* buffer name of file to read */ bname_t bname ; /* buffer name of file to read */
setlocale( LC_CTYPE, "") ; /* expects $LANG like en_GB.UTF-8 */
#if PKCODE & BSD #if PKCODE & BSD
sleep(1); /* Time for window manager. */ sleep(1); /* Time for window manager. */
#endif #endif
#if UNIX
#ifdef SIGWINCH
signal(SIGWINCH, sizesignal);
#endif
#endif
if( argc == 2) { if( argc == 2) {
if( strcmp( argv[ 1], "--help") == 0) { if( strcmp( argv[ 1], "--help") == 0) {
usage() ; usage() ;
@ -325,7 +315,7 @@ int main(int argc, char **argv)
*/ */
static void edinit( char *bname) { static void edinit( char *bname) {
buffer_p bp; buffer_p bp;
struct window *wp; window_p wp;
if( !init_bindings() /* initialize mapping of function to name and key */ if( !init_bindings() /* initialize mapping of function to name and key */
|| NULL == (bp = bfind( bname, TRUE, 0)) /* First buffer */ || NULL == (bp = bfind( bname, TRUE, 0)) /* First buffer */
@ -357,80 +347,67 @@ static void edinit( char *bname) {
wp->w_flag = WFMODE | WFHARD; /* Full. */ wp->w_flag = WFMODE | WFHARD; /* Full. */
} }
/***** Compiler specific Library functions ****/ /***** Compiler specific Library functions ****/
#if RAMSIZE #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.
with SHOWRAM defined, the number is also posted on the /* These routines will allow me to track memory usage by placing a layer on
end of the bottom mode line and is updated whenever it is changed. 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 #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 #endif
} }
return mp; return mp ;
} }
#if 0 void release( void *mp) {
release(mp) if( mp) {
/* release malloced memory and track */ size_t *sp = mp ;
char *mp; /* chunk of RAM to release */ sp-- ;
#endif
void release( void *mp)
{
unsigned *lp; /* ptr to the long containing the block size */
if (mp) {
/* update amount of ram currently malloced */ /* update amount of ram currently malloced */
lp = ((unsigned *) mp) - 1; envram -= *sp ;
envram -= (long) *lp - 2; (free)( sp) ; /* call the function not the macro */
free(mp);
#if RAMSHOW #if RAMSHOW
dspram(); dspram() ;
#endif #endif
} }
} }
#if RAMSHOW #if RAMSHOW
static void dspram( void) static void dspram( void) { /* display the amount of RAM currently malloced */
{ /* display the amount of RAM currently malloced */ char mbuf[ 20] ;
char mbuf[20];
char *sp;
TTmove(term.t_nrow - 1, 70); TTmove( term.t_nrow, term.t_ncol - 12) ;
#if COLOR #if COLOR
TTforg(7); TTforg( 7) ;
TTbacg(0); TTbacg(0) ;
#endif #endif
sprintf(mbuf, "[%lu]", envram); sprintf( mbuf, "[%10u]", envram) ;
sp = &mbuf[0]; char *sp = mbuf ;
while (*sp) while( *sp)
TTputc(*sp++); TTputc( *sp++) ;
TTmove(term.t_nrow, 0);
movecursor(term.t_nrow, 0); TTmove( term.t_nrow, 0) ;
movecursor( term.t_nrow, 0) ;
} }
#endif #endif
#endif #endif
@ -442,42 +419,36 @@ static void dspram( void)
#if CLEAN #if CLEAN
/* /* cexit()
* cexit()
* *
* int status; return status of emacs * int status; return status of emacs
*/ */
void cexit( int status) { void cexit( int status) {
struct buffer *bp; /* buffer list pointer */ /* first clean up the windows */
struct window *wp; /* window list pointer */ window_p wp = wheadp ;
struct window *tp; /* temporary window pointer */ while( wp) {
window_p tp = wp->w_wndp ;
/* first clean up the windows */ free( wp) ;
wp = wheadp; wp = tp ;
while (wp) {
tp = wp->w_wndp;
free(wp);
wp = tp;
} }
wheadp = NULL;
wheadp = NULL ;
/* then the buffers */ /* then the buffers */
bp = bheadp; buffer_p bp ;
while (bp) { while( (bp = bheadp) != NULL) {
bp->b_nwnd = 0; bp->b_nwnd = 0 ;
bp->b_flag = 0; /* don't say anything about a changed buffer! */ bp->b_flag = 0 ; /* don't say anything about a changed buffer! */
zotbuf(bp); zotbuf( bp) ;
bp = bheadp;
} }
/* and the kill buffer */ /* and the kill buffer */
kdelete(); kdelete() ;
/* and the video buffers */ /* and the video buffers */
vtfree(); vtfree() ;
#undef exit (exit)( status) ; /* call the function, not the macro */
exit(status);
} }
#endif #endif

View File

@ -1,6 +1,7 @@
# record seed ## maze.cmd -- draw a block maze
# 5 set $seed # 5 set $seed
set %S $seed set %S $seed # record seed
# setup direction offsets # setup direction offsets
set %D1 0 set %D1 0

View File

@ -16,6 +16,7 @@
#include "bind.h" #include "bind.h"
#include "bindable.h" #include "bindable.h"
#include "buffer.h" #include "buffer.h"
#include "defines.h" /* malloc/allocate */
#include "display.h" #include "display.h"
#include "eval.h" #include "eval.h"
#include "exec.h" #include "exec.h"
@ -49,8 +50,8 @@ const name_bind names[] = {
{"!case-word-lower", lowerword, META | 'L'} , {"!case-word-lower", lowerword, META | 'L'} ,
{"!case-word-upper", upperword, META | 'U'} , {"!case-word-upper", upperword, META | 'U'} ,
{" change-file-name", filename, CTLX | 'N'} , {" change-file-name", filename, CTLX | 'N'} ,
{" change-screen-size", newsize, META | CTL_ | 'D'} , /* M^S */ {" change-screen-size", (fnp_t) newsize, META | CTL_ | 'D'} , /* M^S */
{" change-screen-width", newwidth, META | CTL_ | 'T'} , {" change-screen-width", (fnp_t) newwidth, META | CTL_ | 'T'} ,
{" clear-and-redraw", (fnp_t) redraw, CTL_ | 'L'} , {" clear-and-redraw", (fnp_t) redraw, CTL_ | 'L'} ,
{" clear-message-line", (fnp_t) clrmes, 0} , {" clear-message-line", (fnp_t) clrmes, 0} ,
{" copy-region", copyregion, META | 'W'} , {" copy-region", copyregion, META | 'W'} ,
@ -191,7 +192,7 @@ const name_bind names[] = {
{" shell-command", spawn, CTLX | '!'} , {" shell-command", spawn, CTLX | '!'} ,
{" shrink-window", shrinkwind, CTLX | CTL_ | 'Z'} , {" shrink-window", shrinkwind, CTLX | CTL_ | 'Z'} ,
{" split-current-window", splitwind, CTLX | '2'} , {" split-current-window", splitwind, CTLX | '2'} ,
{" store-macro", storemac, 0} , {" store-macro", (fnp_t) storemac, 0} ,
{" store-procedure", storeproc, 0} , {" store-procedure", storeproc, 0} ,
#if BSD | SVR4 #if BSD | SVR4
{" suspend-emacs", bktoshell, CTLX | 'D'} , /* BSD MS */ {" suspend-emacs", bktoshell, CTLX | 'D'} , /* BSD MS */
@ -201,7 +202,7 @@ const name_bind names[] = {
{" unbind-key", unbindkey, META | CTL_ | 'K'} , {" unbind-key", unbindkey, META | CTL_ | 'K'} ,
{" universal-argument", (fnp_t) unarg, CTL_ | 'U'} , {" universal-argument", (fnp_t) unarg, CTL_ | 'U'} ,
{" unmark-buffer", unmark, META | '~'} , {" unmark-buffer", unmark, META | '~'} ,
{" update-screen", upscreen, 0} , {" update-screen", (fnp_t) upscreen, 0} ,
{" view-file", viewfile, CTLX | CTL_ | 'V'} , {" view-file", viewfile, CTLX | CTL_ | 'V'} ,
{"!wrap-word", wrapword, META | SPEC | 'W'} , /* hook */ {"!wrap-word", wrapword, META | SPEC | 'W'} , /* hook */
{" write-file", filewrite, CTLX | CTL_ | 'W'} , {" write-file", filewrite, CTLX | CTL_ | 'W'} ,

View File

@ -2,7 +2,7 @@
#ifndef _PKLOCK_H_ #ifndef _PKLOCK_H_
#define _PKLOCK_H_ #define _PKLOCK_H_
#include "estruct.h" #include "defines.h" /* FILOCK, BSD, SVR4 */
#if (FILOCK && BSD) || SVR4 #if (FILOCK && BSD) || SVR4
char *dolock( const char *fname) ; char *dolock( const char *fname) ;

91
posix.c
View File

@ -1,18 +1,17 @@
/* posix.c -- posix implementation of termio.h */ /* posix.c -- posix implementation of termio.h */
#ifdef POSIX
#include "termio.h" #include "termio.h"
/* posix.c #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 /* The functions in this file negotiate with the operating system for
* display. All operating systems. characters, and write characters in a barely buffered fashion on the
* display. All operating systems.
* modified by Petri Kutvonen
* 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 based on termio.c, with all the old cruft removed, and
fixed for termios rather than the old termio.. Linus Torvalds
*/ */
#include <errno.h> #include <errno.h>
@ -24,21 +23,19 @@
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
#include "estruct.h"
#include "retcode.h" #include "retcode.h"
#include "utf8.h" #include "utf8.h"
int ttrow = HUGE ; /* Row location of HW cursor */ int ttrow = -1 ; /* Row location of HW cursor */
int ttcol = HUGE ; /* Column 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. /* Define missing macroes for BSD and CYGWIN environment */
*/ #if BSD
#if BSD || defined(SYSV) && (defined(_DARWIN_C_SOURCE) || defined(_FREEBSD_C_SOURCE))
#define OLCUC 0000002 #define OLCUC 0000002
#define XCASE 0000004 #define XCASE 0000004
#endif #endif
#ifdef CYGWIN #ifdef __CYGWIN__ /* gcc predefined (see cpp -dM) */
#define XCASE 0 #define XCASE 0
#define ECHOPRT 0 #define ECHOPRT 0
#define PENDIN 0 #define PENDIN 0
@ -96,10 +93,8 @@ void ttopen(void)
kbdflgs = fcntl(0, F_GETFL, 0); kbdflgs = fcntl(0, F_GETFL, 0);
kbdpoll = FALSE; kbdpoll = FALSE;
/* on all screens we are not sure of the initial position /* on all screens we are not sure of the initial position of the cursor */
of the cursor */ ttrow = ttcol = -1 ;
ttrow = 999;
ttcol = 999;
} }
/* /*
@ -154,27 +149,28 @@ void ttflush(void)
exit(15); 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; /* Read a character from the terminal, performing no editing and doing no
if (!count) { echo at all.
count = read(0, buffer, sizeof(buffer)); */
if (count <= 0) int ttgetc( void) {
return 0; static char buffer[ 32] ;
pending = count; 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) if (c >= 32 && c < 128)
goto done; goto done;
@ -191,7 +187,7 @@ int ttgetc(void)
* delay for some *very* unusual utf8 character * delay for some *very* unusual utf8 character
* input. * input.
*/ */
expected = 2; int expected = 2;
if ((c & 0xe0) == 0xe0) if ((c & 0xe0) == 0xe0)
expected = 6; expected = 6;
@ -225,9 +221,10 @@ int ttgetc(void)
bytes = utf8_to_unicode(buffer, 0, pending, &c); bytes = utf8_to_unicode(buffer, 0, pending, &c);
done: done:
pending -= bytes; #endif
memmove(buffer, buffer+bytes, pending); pending -= bytes ;
return c; memmove( buffer, buffer + bytes, pending) ;
return c ;
} }
/* typahead: Check to see if any characters are already in the /* typahead: Check to see if any characters are already in the
@ -247,8 +244,6 @@ int typahead(void)
return x; return x;
} }
#else #endif
typedef void _pedantic_empty_translation_unit ;
#endif /* not POSIX */
/* end of posix.c */ /* end of posix.c */

View File

@ -14,8 +14,8 @@
#include "basic.h" #include "basic.h"
#include "buffer.h" #include "buffer.h"
#include "defines.h"
#include "display.h" #include "display.h"
#include "estruct.h"
#include "execute.h" #include "execute.h"
#include "input.h" #include "input.h"
#include "line.h" #include "line.h"
@ -219,30 +219,31 @@ boolean setccol( int pos) {
*/ */
BBINDABLE( twiddle) { BBINDABLE( twiddle) {
unicode_t c ; unicode_t c ;
boolean eof_f = FALSE ;
assert( !(curbp->b_mode & MDVIEW)) ; assert( !(curbp->b_mode & MDVIEW)) ;
int len = llength( curwp->w_dotp) ; 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 ; return FALSE ;
if( curwp->w_doto == len) { /* at end of line */ if( curwp->w_doto == len) { /* at end of line */
backchar( FALSE, 1) ; 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) ; backchar( FALSE, 1) ;
len = lgetchar( &c) ; /* len => unicode or extended ASCII */
ldelchar( 1, FALSE) ;
forwchar( FALSE, 1) ;
if( len == 1) if( len == 1)
linsert_byte( 1, c) ; linsert_byte( 1, c) ;
else else
linsert( 1, c) ; linsert( 1, c) ;
if( eof_f == TRUE)
forwchar( FALSE, 1) ;
lchange( WFEDIT) ; lchange( WFEDIT) ;
return TRUE ; 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 */ char *tstring ; /* string to add */
/* ask for string to insert */ /* ask for string to insert */

View File

@ -12,7 +12,7 @@
#include <stddef.h> #include <stddef.h>
#include "buffer.h" #include "buffer.h"
#include "estruct.h" #include "defines.h"
#include "line.h" #include "line.h"
#include "mlout.h" #include "mlout.h"
#include "random.h" #include "random.h"

View File

@ -65,8 +65,8 @@
#include "basic.h" #include "basic.h"
#include "buffer.h" #include "buffer.h"
#include "defines.h"
#include "display.h" #include "display.h"
#include "estruct.h"
#include "input.h" #include "input.h"
#include "isa.h" #include "isa.h"
#include "line.h" #include "line.h"

54
sharpmaz.cmd Normal file
View File

@ -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 &not &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 &not &equ $curchar 32
set %v &add %v %inc
!endif
set %inc &tim %inc 2
!return

95
spawn.c
View File

@ -12,11 +12,9 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "defines.h"
#include "buffer.h" #include "buffer.h"
#include "defines.h"
#include "display.h" #include "display.h"
#include "estruct.h"
#include "exec.h" #include "exec.h"
#include "file.h" #include "file.h"
#include "flook.h" #include "flook.h"
@ -27,8 +25,6 @@
#if USG | BSD #if USG | BSD
#include <signal.h> #include <signal.h>
#ifdef SIGWINCH
#endif
#endif #endif
@ -173,97 +169,88 @@ BINDABLE( execprg) {
/* Pipe a one line command into a window /* Pipe a one line command into a window
* Bound to ^X @ * Bound to pipe-command ^X @
*/ */
BINDABLE( pipecmd) { BINDABLE( pipecmd) {
int s ; /* return status from CLI */ window_p wp ; /* pointer to new window */
struct window *wp ; /* pointer to new window */
buffer_p bp ; /* pointer to buffer to zot */
char *mlarg ; char *mlarg ;
char *line ; /* command line send to shell */ const char filnam[] = "command" ;
static char bname[] = "command" ;
static char filnam[ NSTRING] = "command" ;
/* don't allow this command if restricted */ /* don't allow this command if restricted */
if( restflag) if( restflag)
return resterr() ; return resterr() ;
/* get the command to pipe in */ /* get the command to pipe in */
s = newmlarg( &mlarg, "@", 0) ; int s = newmlarg( &mlarg, "pipe-command: ", 0) ;
if( s != TRUE) if( s != TRUE)
return s ; return s ;
line = malloc( strlen( mlarg) + strlen( filnam) + 2) ; char *cmdline = malloc( strlen( mlarg) + strlen( filnam) + 4) ;
if( line == NULL) { if( cmdline == NULL) {
free( mlarg) ; free( mlarg) ;
return FALSE ; return FALSE ;
} }
strcpy( line, mlarg) ; strcpy( cmdline, mlarg) ;
free( mlarg) ; free( mlarg) ;
strcat( cmdline, " > ") ;
strcat( cmdline, filnam) ;
/* get rid of the command output buffer if it exists */ /* get rid of the command output buffer if it exists */
if ((bp = bfind(bname, FALSE, 0)) != FALSE) { buffer_p bp = bfind( filnam, FALSE, 0) ;
/* try to make sure we are off screen */ if( bp != NULL) {
wp = wheadp; /* try to make sure we are off screen */
while (wp != NULL) { for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
if (wp->w_bufp == bp) { if( wp->w_bufp == bp) {
#if PKCODE #if PKCODE
if (wp == curwp) if( wp == curwp)
delwind(FALSE, 1); delwind( FALSE, 1) ;
else else
onlywind(FALSE, 1); onlywind( FALSE, 1) ;
break; break ;
#else #else
onlywind(FALSE, 1); onlywind( FALSE, 1) ;
break; break ;
#endif #endif
} }
wp = wp->w_wndp;
} }
if( zotbuf( bp) != TRUE) { if( zotbuf( bp) != TRUE) {
free( line) ; free( cmdline) ;
return FALSE ; return FALSE ;
} }
} }
#if USG | BSD #if USG | BSD
TTflush(); TTflush();
TTclose(); /* stty to old modes */ TTclose(); /* stty to old modes */
TTkclose(); TTkclose();
strcat( line, ">") ; ue_system( cmdline) ;
strcat( line, filnam) ; free( cmdline) ;
ue_system( line) ;
free( line) ;
TTopen(); TTopen();
TTkopen(); TTkopen();
TTflush(); TTflush();
sgarbf = TRUE; sgarbf = TRUE;
s = TRUE; s = TRUE;
#else #else
if (s != TRUE) if( s != TRUE)
return s; return s;
#endif #endif
/* split the current window to make room for the command output */ /* split the current window to make room for the command output
if (splitwind(FALSE, 1) == FALSE) ** and read the stuff in */
return FALSE; if( splitwind( FALSE, 1) == FALSE
|| getfile( filnam, FALSE) == FALSE)
return FALSE ;
/* and read the stuff in */ /* make this window in VIEW mode, update all mode lines */
if (getfile(filnam, FALSE) == FALSE) curwp->w_bufp->b_mode |= MDVIEW ;
return FALSE; for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp)
wp->w_flag |= WFMODE ;
/* make this window in VIEW mode, update all mode lines */ /* and get rid of the temporary file */
curwp->w_bufp->b_mode |= MDVIEW; unlink( filnam) ;
wp = wheadp; return TRUE ;
while (wp != NULL) {
wp->w_flag |= WFMODE;
wp = wp->w_wndp;
}
/* and get rid of the temporary file */
unlink(filnam);
return TRUE;
} }

18
tcap.c
View File

@ -20,8 +20,8 @@
#include <curses.h> #include <curses.h>
#include <term.h> #include <term.h>
#include "defines.h"
#include "display.h" #include "display.h"
#include "estruct.h"
#include "termio.h" #include "termio.h"
#if TERMCAP #if TERMCAP
@ -83,7 +83,7 @@ static char *_UP, _PC, *CM, *CE, *CL, *SO, *SE;
static char *CS, *DL, *AL, *SF, *SR; static char *CS, *DL, *AL, *SF, *SR;
# endif # endif
struct terminal term = { terminal_t term = {
480, /* actual 479 on 2560x1440 landscape terminal window */ 480, /* actual 479 on 2560x1440 landscape terminal window */
2550, /* actual 2541 */ 2550, /* actual 2541 */
0, /* These four values are set dynamically at open time. */ 0, /* These four values are set dynamically at open time. */
@ -231,16 +231,14 @@ static void tcapclose(void)
} }
# endif # endif
static void tcapkopen(void) static void tcapkopen( void) {
{
# if PKCODE # if PKCODE
putpad(TI); putpad( TI) ;
ttflush(); ttflush() ;
ttrow = 999; ttrow = ttcol = -1 ;
ttcol = 999; sgarbf = TRUE ;
sgarbf = TRUE;
# endif # endif
strcpy(sres, "NORMAL"); strcpy(sres, "NORMAL") ;
} }
static void tcapkclose(void) static void tcapkclose(void)

View File

@ -6,45 +6,45 @@
#include "retcode.h" #include "retcode.h"
#include "utf8.h" #include "utf8.h"
/* The editor communicates with the display using a high level interface. A /* The editor communicates with the display using a high level interface.
* "TERM" structure holds useful variables, and indirect pointers to routines A "TERM" structure holds useful variables, and indirect pointers to
* that do useful operations. The low level get and put routines are here too. routines that do useful operations. The low level get and put routines
* This lets a terminal, in addition to having non standard commands, have are here too. This lets a terminal, in addition to having non standard
* funny get and put character code too. The calls might get changed to commands, have funny get and put character code too. The calls might
* "termp->t_field" style in the future, to make it possible to run more than get changed to "termp->t_field" style in the future, to make it possible
* one terminal type. to run more than one terminal type.
*/ */
struct terminal { typedef struct {
const short t_maxrow ; /* max number of rows allowable */ const short t_maxrow ; /* max number of rows allowable */
const short t_maxcol ; /* max number of columns allowable */ const short t_maxcol ; /* max number of columns allowable */
short t_mrow ; /* max number of rows displayable */ short t_mrow ; /* max number of rows displayable */
short t_nrow ; /* current number of rows displayed */ short t_nrow ; /* current number of rows displayed */
short t_mcol ; /* max number of rows displayable */ short t_mcol ; /* max number of rows displayable */
short t_ncol ; /* current number of columns displayed */ short t_ncol ; /* current number of columns displayed */
short t_margin; /* min margin for extended lines */ short t_margin ; /* min margin for extended lines */
short t_scrsiz; /* size of scroll region " */ short t_scrsiz ; /* size of scroll region */
int t_pause; /* # times thru update to pause */ int t_pause ; /* # times thru update to pause */
void (*t_open)(void); /* Open terminal at the start. */ void (*t_open)( void) ; /* Open terminal at the start */
void (*t_close)(void); /* Close terminal at end. */ void (*t_close)( void) ; /* Close terminal at end. */
void (*t_kopen)(void); /* Open keyboard */ void (*t_kopen)( void) ; /* Open keyboard */
void (*t_kclose)(void); /* close keyboard */ void (*t_kclose)( void) ; /* close keyboard */
int (*t_getchar)(void); /* Get character from keyboard. */ int (*t_getchar)( void) ; /* Get character from keyboard */
int (*t_putchar)( unicode_t) ; /* Put character to display. */ int (*t_putchar)( unicode_t) ; /* Put character to display */
void (*t_flush) (void); /* Flush output buffers. */ void (*t_flush) (void) ; /* Flush output buffers */
void (*t_move)(int, int);/* Move the cursor, origin 0. */ void (*t_move)( int, int) ; /* Move the cursor, origin 0 */
void (*t_eeol)(void); /* Erase to end of line. */ void (*t_eeol)( void) ; /* Erase to end of line */
void (*t_eeop)(void); /* Erase to end of page. */ void (*t_eeop)( void) ; /* Erase to end of page */
void (*t_beep)(void); /* Beep. */ void (*t_beep)( void) ; /* Beep */
void (*t_rev)(int); /* set reverse video state */ void (*t_rev)( int) ; /* set reverse video state */
int (*t_rez)(char *); /* change screen resolution */ int (*t_rez)( char *) ; /* change screen resolution */
#if COLOR #if COLOR
int (*t_setfor) (); /* set forground color */ int (*t_setfor)() ; /* set forground color */
int (*t_setback) (); /* set background color */ int (*t_setback)() ; /* set background color */
#endif #endif
#if SCROLLCODE #if SCROLLCODE
void (*t_scroll)(int, int,int); /* scroll a region of the screen */ void (*t_scroll)( int, int,int) ; /* scroll a region of the screen */
#endif #endif
}; } terminal_t ;
/* TEMPORARY macros for terminal I/O (to be placed in a machine dependant /* TEMPORARY macros for terminal I/O (to be placed in a machine dependant
place later) place later)
@ -68,11 +68,8 @@ struct terminal {
#define TTbacg (*term.t_setback) #define TTbacg (*term.t_setback)
#endif #endif
/* Terminal table defined only in term.c */ /* Terminal table defined only in tcap.c */
extern struct terminal term ; extern terminal_t term ;
extern int ttrow ; /* Row location of HW cursor */
extern int ttcol ; /* Column location of HW cursor */
extern boolean eolexist ; /* does clear to EOL exist? */ extern boolean eolexist ; /* does clear to EOL exist? */
extern boolean revexist ; /* does reverse video exist? */ extern boolean revexist ; /* does reverse video exist? */

View File

@ -1,21 +1,19 @@
/* termio.c -- implements termio.h */ /* termio.c -- implements termio.h */
#if !defined( POSIX)
#include "termio.h" #include "termio.h"
/* TERMIO.C #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. /* The functions in this file negotiate with the operating system for
* All operating systems. characters, and write characters in a barely buffered fashion on the
* display. All operating systems.
* modified by Petri Kutvonen
modified by Petri Kutvonen
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "estruct.h"
#include "retcode.h" #include "retcode.h"
#include "utf8.h" #include "utf8.h"
@ -23,8 +21,8 @@
#include <unistd.h> #include <unistd.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
int ttrow = HUGE ; /* Row location of HW cursor */ int ttrow = -1 ; /* Row location of HW cursor */
int ttcol = HUGE ; /* Column location of HW cursor */ int ttcol = -1 ; /* Column location of HW cursor */
#if USG /* System V */ #if USG /* System V */
@ -141,8 +139,7 @@ void ttopen(void)
/* on all screens we are not sure of the initial position /* on all screens we are not sure of the initial position
of the cursor */ of the cursor */
ttrow = 999; ttrow = ttcol = -1 ;
ttcol = 999;
} }
/* /*
@ -258,14 +255,12 @@ int typahead( void)
return kbdqp; return kbdqp;
#endif #endif
#if !UNIX # if !UNIX
return FALSE; return FALSE;
#endif # endif
} }
#endif # endif
#else
typedef void _pedantic_empty_translation_unit ;
#endif /* not POSIX */ #endif /* not POSIX */
/* end of termio.c */ /* end of termio.c */

View File

@ -6,8 +6,6 @@
#define TYPEAH 1 /* type ahead causes update to be skipped */ #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 ttrow ; /* Row location of HW cursor */
extern int ttcol ; /* Column location of HW cursor */ extern int ttcol ; /* Column location of HW cursor */

163
ue.rc
View File

@ -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 &not &seq $cbufname "emacs.hlp"
write-message "(Loading Help)"
!force help
!if &not &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"

122
utf8.c
View File

@ -1,27 +1,23 @@
/* utf8.c -- implements utf8.h, converts between unicode and UTF-8 */ /* utf8.c -- implements utf8.h, conversion between unicode and UTF-8 */
#define _XOPEN_SOURCE /* wcwidth in wchar.h */
#include "utf8.h" #include "utf8.h"
#include <assert.h> #include <assert.h>
#include <wchar.h> #include <wchar.h> /* either _XOPEN_SOURCE or _GNU_SOURCE */
/* Display width of UTF-8 character */ /* Display width of UTF-8 character */
int _utf8_width( unicode_t c) { int _utf8_width( unicode_t c) {
#if CYGWIN #if __SIZEOF_WCHAR_T__ == 2 /* wcwidth only supports UTF-16 */
assert( sizeof( wchar_t) == 2) ; /* wcwidth only supports UTF-16 */ return (c < 0x10000) ? wcwidth( (wchar_t) c) : -1 ;
return (c < 0x10000) ? wcwidth( (wchar_t) c) : -1 ;
#else #else
return wcwidth( (wchar_t) c) ; return wcwidth( (wchar_t) c) ;
#endif #endif
} }
int utf8_width( unicode_t c) { int utf8_width( unicode_t c) {
int w = _utf8_width( c) ; int w = _utf8_width( c) ;
return (w < 0) ? 2 : w ; /* display \u if can't figure out width */ 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". * are happily accepted and decoded, as are the various "invalid values".
*/ */
unsigned utf8_to_unicode( const char *line, unsigned index, unsigned len, unsigned utf8_to_unicode( const char *line, unsigned index, unsigned len,
unicode_t *res) { unicode_t *res) {
unicode_t value ; assert( index < len) ;
unsigned c ; unsigned c = *res = (unsigned char) line[ index] ;
unsigned bytes, mask, i;
if( index >= len) /* 0xxxxxxx is valid one byte utf8
return 0 ;
*res = c = line[ index] & 0xFFU ;
/*
* 0xxxxxxx is valid one byte utf8
* 10xxxxxx is invalid UTF-8 start byte, we assume it is Latin1 * 10xxxxxx is invalid UTF-8 start byte, we assume it is Latin1
* 1100000x is start of overlong encoding sequence * 1100000x is start of overlong encoding sequence
* Sequence longer than 4 bytes are invalid * Sequence longer than 4 bytes are invalid
* Last valid code is 0x10FFFF, encoding start with 0xF4 * Last valid code is 0x10FFFF, encoding start with 0xF4
*/ */
if( c <= 0xC1 || c > 0xF4) if( c <= 0xC1 || c > 0xF4)
return 1; return 1 ;
/* Ok, it's 11xxxxxx, do a stupid decode */ /* Ok, it's 11xxxxxx, do a stupid decode */
mask = 0x20; unsigned mask = 0x20 ;
bytes = 2; unsigned bytes = 2 ;
while( (c & mask) != 0) { while( (c & mask) != 0) {
bytes++; bytes++ ;
mask >>= 1; mask >>= 1 ;
} }
/* bytes is in range [2..4] as c was in range [C2..F4] */ /* bytes is in range [2..4] as c was in range [C2..F4] */
len -= index; len -= index ;
if (bytes > len) if( bytes > len)
return 1; return 1 ;
value = c & (mask-1); unicode_t value = c & (mask - 1) ;
/* Ok, do the bytes */ /* Ok, do the bytes */
line += index; line += index ;
for (i = 1; i < bytes; i++) { for( unsigned i = 2 ; i <= bytes ; i++) {
c = line[i] & 0xFFU ; c = (unsigned char) *++line ;
if ((c & 0xc0) != 0x80) if( (c & 0xc0) != 0x80)
return 1; return 1 ;
value = (value << 6) | (c & 0x3f);
value = (value << 6) | (c & 0x3f) ;
} }
if( value > 0x10FFFF) /* Avoid 110000 - 13FFFF */ if( value > 0x10FFFF) /* Avoid 110000 - 13FFFF */
return 1 ; return 1 ;
*res = value; *res = value ;
return bytes; return bytes ;
} }
@ -106,12 +96,12 @@ unsigned unicode_to_utf8( unicode_t c, char *utf8) {
assert( c <= 0x10FFFF) ; assert( c <= 0x10FFFF) ;
#ifdef NDEBUG #ifdef NDEBUG
if( c > 0x10FFFF) /* Let's assume this is due to sign extension */ if( c > 0x10FFFF) /* Let's assume this is due to sign extension */
c &= 0xFF ; c &= 0xFF ;
#endif #endif
if( c <= 0x7f) if( c <= 0x7f)
*utf8 = (char) c ; *utf8 = (char) c ;
else { else {
unsigned prefix = 0x40 ; unsigned prefix = 0x40 ;
char *p = utf8 ; char *p = utf8 ;
@ -122,38 +112,38 @@ unsigned unicode_to_utf8( unicode_t c, char *utf8) {
c >>= 6 ; c >>= 6 ;
} while( c >= prefix) ; } while( c >= prefix) ;
*p-- = *utf8 ; *p-- = *utf8 ;
*utf8++ = (char) (c - 2 * prefix) ; *utf8++ = (char) (c - 2 * prefix) ;
if( utf8 < p) { /* swap middle two bytes if 4 bytes utf-8 code */ if( utf8 < p) { /* swap middle two bytes if 4 bytes utf-8 code */
char c = *p ; char c = *p ;
*p = *utf8 ; *p = *utf8 ;
*utf8 = c ; *utf8 = c ;
} }
} }
return bytes ; return bytes ;
} }
unsigned utf8_revdelta( unsigned char *p, unsigned pos) { unsigned utf8_revdelta( unsigned char *p, unsigned pos) {
unsigned delta = 0 ; unsigned delta = 0 ;
if( (*p & 0xC0) == 0x80) { if( (*p & 0xC0) == 0x80) {
unsigned char c ; unsigned char c ;
c = *--p ; c = *--p ;
if( (c & 0xE0) == 0xC0) /* valid 2 bytes unicode seq */ if( (c & 0xE0) == 0xC0) /* valid 2 bytes unicode seq */
delta = 1 ; delta = 1 ;
else if( ((c & 0xC0) == 0x80) && (pos > 1)) { else if( ((c & 0xC0) == 0x80) && (pos > 1)) {
c = *--p ; c = *--p ;
if( (c & 0xF0) == 0xE0) /* valid 3 bytes unicode seq */ if( (c & 0xF0) == 0xE0) /* valid 3 bytes unicode seq */
delta = 2 ; delta = 2 ;
else if( ((c & 0xC0) == 0x80) && (pos > 2)) else if( ((c & 0xC0) == 0x80) && (pos > 2))
if( (p[ -1] & 0xF8) == 0xF0) /* valid 4 bytes unicode seq */ if( (p[ -1] & 0xF8) == 0xF0) /* valid 4 bytes unicode seq */
delta = 3 ; delta = 3 ;
} }
} }
return delta ; return delta ;
} }

2
utf8.h
View File

@ -1,4 +1,4 @@
/* utf8.h -- */ /* utf8.h -- conversion between unicode and UTF-8 */
#ifndef _UTF8_H_ #ifndef _UTF8_H_
#define _UTF8_H_ #define _UTF8_H_

135
window.c
View File

@ -6,11 +6,12 @@
*/ */
#include <assert.h> #include <assert.h>
#include <stdlib.h> /* malloc(), free() */
#include "basic.h" #include "basic.h"
#include "buffer.h" #include "buffer.h"
#include "defines.h"
#include "display.h" /* upmode() */ #include "display.h" /* upmode() */
#include "estruct.h"
#include "execute.h" #include "execute.h"
#include "line.h" #include "line.h"
#include "mlout.h" #include "mlout.h"
@ -52,7 +53,7 @@ TBINDABLE( redraw) {
/* The command make the next window (next => down the screen) the current /* The command make the next window (next => down the screen) the current
window. There are no real errors, although the command does nothing if 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 <n>th window from the top with an argument this command finds the <n>th window from the top
@ -318,7 +319,10 @@ BINDABLE( splitwind) {
return FALSE ; return FALSE ;
} }
wp = xmalloc( sizeof *wp) ; wp = malloc( sizeof *wp) ;
if( wp == NULL)
return mloutfail( "Out of memory") ;
++curbp->b_nwnd; /* Displayed twice. */ ++curbp->b_nwnd; /* Displayed twice. */
wp->w_bufp = curbp; wp->w_bufp = curbp;
wp->w_dotp = curwp->w_dotp; 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 /* resize the screen, re-writing the screen
* *
* int f; default flag * int f; default flag
* int n; numeric argument * int n; numeric argument
*/ */
BINDABLE( newsize) { BBINDABLE( newsize) {
window_p wp; /* current window being examined */ 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 */
/* if the command defaults, assume the largest */ /* if the command defaults, assume the largest */
if (f == FALSE) if( f == FALSE)
n = term.t_mrow ; n = term.t_mrow ;
/* make sure it's in range */ /* 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") ; return mloutfail( "%%Screen size out of range") ;
if (term.t_nrow == n - 1) if( term.t_nrow == n - 1)
return TRUE; /* no change */
else if (term.t_nrow < n - 1) { return TRUE ;
else if( term.t_nrow < n - 1) {
/* new size is bigger */
/* go to the last window */ /* go to the last window */
wp = wheadp; for( wp = wheadp ; wp->w_wndp != NULL ; wp = wp->w_wndp)
while (wp->w_wndp != NULL) ;
wp = wp->w_wndp;
/* and enlarge it as needed */ /* and enlarge it as needed */
wp->w_ntrows = n - wp->w_toprow - 2; adjust( wp, n) ;
wp->w_flag |= WFHARD | WFMODE;
} else { } else {
/* new size is smaller */
/* rebuild the window structure */ /* rebuild the window structure */
assert( wheadp->w_toprow == 0) ; /* proves coverity wrong */ assert( wheadp->w_toprow == 0) ; /* proves coverity wrong */
nextwp = wheadp; window_p lastwp = NULL ;
wp = NULL; for( window_p nextwp = wheadp ; nextwp != NULL ; ) {
lastwp = NULL; wp = nextwp ;
while (nextwp != NULL) { nextwp = wp->w_wndp ;
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 */ /* 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 */ /* save the point/mark if needed */
if (--wp->w_bufp->b_nwnd == 0) { if( --wp->w_bufp->b_nwnd == 0) {
wp->w_bufp->b_dotp = wp->w_dotp; wp->w_bufp->b_dotp = wp->w_dotp ;
wp->w_bufp->b_doto = wp->w_doto; wp->w_bufp->b_doto = wp->w_doto ;
wp->w_bufp->b_markp = wp->w_markp; wp->w_bufp->b_markp = wp->w_markp ;
wp->w_bufp->b_marko = wp->w_marko; wp->w_bufp->b_marko = wp->w_marko ;
} }
/* update curwp and lastwp if needed */ /* update curwp and lastwp if needed */
if (wp == curwp) if( wp == curwp) {
curwp = wheadp; curwp = wheadp ;
curbp = curwp->w_bufp; curbp = curwp->w_bufp ;
if (lastwp != NULL) }
lastwp->w_wndp = NULL;
/* free the structure */ /* free the structure */
free((char *) wp); free( wp) ;
wp = NULL; lastwp->w_wndp = NULL ;
} else { } else {
/* need to change this window size? */ /* need to change this window size? */
lastline = wp->w_toprow + wp->w_ntrows - 1; if( (wp->w_toprow + wp->w_ntrows - 1) >= n - 2)
if (lastline >= n - 2) { adjust( wp, n) ;
wp->w_ntrows =
n - wp->w_toprow - 2;
wp->w_flag |= WFHARD | WFMODE;
}
}
lastwp = wp; lastwp = wp ;
}
} }
} }
/* screen is garbage */ /* screen is garbage */
term.t_nrow = n - 1; term.t_nrow = n - 1 ;
sgarbf = TRUE; sgarbf = TRUE ;
return TRUE; return TRUE ;
} }
@ -648,31 +647,25 @@ BINDABLE( newsize) {
* int f; default flag * int f; default flag
* int n; numeric argument * int n; numeric argument
*/ */
BINDABLE( newwidth) { BBINDABLE( newwidth) {
window_p wp;
/* if the command defaults, assume the largest */ /* if the command defaults, assume the largest */
if (f == FALSE) if( f == FALSE)
n = term.t_mcol; n = term.t_mcol ;
/* make sure it's in range */ /* 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") ; return mloutfail( "%%Screen width out of range") ;
/* otherwise, just re-width it (no big deal) */ /* otherwise, just re-width it (no big deal) */
term.t_ncol = n; term.t_ncol = n ;
term.t_margin = n / 10; updmargin() ;
term.t_scrsiz = n - (term.t_margin * 2);
/* florce all windows to redraw */ /* force all windows to redraw */
wp = wheadp; for( window_p wp = wheadp ; wp; wp = wp->w_wndp)
while (wp) { wp->w_flag |= WFHARD | WFMOVE | WFMODE ;
wp->w_flag |= WFHARD | WFMOVE | WFMODE;
wp = wp->w_wndp;
}
sgarbf = TRUE;
return TRUE; sgarbf = TRUE ;
return TRUE ;
} }
int getwpos(void) int getwpos(void)

View File

@ -55,8 +55,8 @@ extern window_p wheadp ; /* Head of list of windows */
BINDABLE( enlargewind) ; BINDABLE( enlargewind) ;
BINDABLE( mvdnwind) ; BINDABLE( mvdnwind) ;
BINDABLE( mvupwind) ; BINDABLE( mvupwind) ;
BINDABLE( newsize) ; BBINDABLE( newsize) ;
BINDABLE( newwidth) ; BBINDABLE( newwidth) ;
BINDABLE( nextwind) ; BINDABLE( nextwind) ;
BINDABLE( onlywind) ; BINDABLE( onlywind) ;
BINDABLE( prevwind) ; BINDABLE( prevwind) ;

2
word.c
View File

@ -14,7 +14,7 @@
#include "basic.h" #include "basic.h"
#include "buffer.h" #include "buffer.h"
#include "estruct.h" #include "defines.h"
#include "isa.h" #include "isa.h"
#include "line.h" #include "line.h"
#include "mlout.h" #include "mlout.h"

View File

@ -1,5 +1,4 @@
/* wrapper.c -- implements wrapper.h */ /* wrapper.c -- implements wrapper.h */
#include "wrapper.h" #include "wrapper.h"
#include <stdio.h> #include <stdio.h>
@ -26,12 +25,4 @@ void xmkstemp( char *template) {
close( fd) ; close( fd) ;
} }
void *xmalloc( size_t size) {
void *ret = malloc( size) ;
if( !ret)
die( "Out of memory") ;
return ret ;
}
/* end of wrapper.c */ /* end of wrapper.c */

View File

@ -2,11 +2,7 @@
#ifndef WRAPPER_H_ #ifndef WRAPPER_H_
#define WRAPPER_H_ #define WRAPPER_H_
#include <stdlib.h> /* size_t */
void xmkstemp( char *fname_template) ; void xmkstemp( char *fname_template) ;
void *xmalloc( size_t size) ;
#endif #endif
/* end of wrapper.h */ /* end of wrapper.h */