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
export E Q
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
# for windows based target, insure we strip the variant part
# CYGWIN_NT-6.1, CYGWIN_NT-6.1-WOW, CYGWIN_NT-6.1-WOW64, MSYS_NT-10.0-19042
uname_S := $(shell sh -c 'echo $(uname_S) | sed s/_.*$$//')
PROGRAM=ue
CC=gcc
@ -25,18 +20,7 @@ WARNINGS=-pedantic -Wall -Wextra -Wstrict-prototypes -Wno-unused-parameter
CFLAGS=-O2 $(WARNINGS)
LDFLAGS=-s
LIBS=-lcurses
DEFINES=-DAUTOCONF -DPROGRAM=$(PROGRAM) # -DNDEBUG
ifeq ($(uname_S),Linux)
DEFINES += -DPOSIX -DUSG
else ifeq ($(uname_S),CYGWIN)
DEFINES += -DCYGWIN -DSYSV
else ifeq ($(uname_S),MSYS)
DEFINES += -DCYGWIN -DSYSV
else ifeq ($(uname_S),NetBSD)
DEFINES += -DPOSIX -DBSD=1
else
$(error $(uname_S) needs configuration)
endif
DEFINES=-DPROGRAM=$(PROGRAM) -D_GNU_SOURCE # -DNDEBUG
BINDIR=/usr/bin
LIBDIR=/usr/lib

View File

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

View File

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

View File

@ -1,8 +1,9 @@
/* buffer.c -- implements buffer.h */
#include "buffer.h"
/* Buffer management. Some of the functions are internal, and some are actually attached to
user keys. Like everyone else, they set hints for the display system.
/* Buffer management. Some of the functions are internal, and some are
actually attached to user keys. Like everyone else, they set hints for
the display system.
modified by Petri Kutvonen
*/
@ -11,9 +12,9 @@
#include <string.h>
#include "defines.h"
#include "estruct.h"
#include "file.h"
#include "input.h"
#include "list.h"
#include "mlout.h"
#include "utf8.h"
#include "util.h"
@ -326,13 +327,12 @@ static unsigned int utf8_disp_len( const char *s) {
static int makelist( int iflag) {
buffer_p bp;
int s;
char line[ FNAMSTART + sizeof( fname_t)] ;
blistp->b_flag &= ~BFCHG; /* Don't complain! Mute bclear() */
if ((s = bclear(blistp)) != TRUE) /* Blow old text away */
return s;
int s = bclear( blistp) ; /* Blow old text away */
if( s != TRUE)
return s ;
blistp->b_fname[ 0] = 0 ; /* in case of user override */
@ -346,19 +346,15 @@ static int makelist( int iflag) {
return FALSE ;
/* output the list of buffers */
for( bp = bheadp ; bp != NULL ; bp = bp->b_bufp) { /* For all buffers */
char *cp1, *cp2 ;
for( buffer_p bp = bheadp ; bp != NULL ; bp = bp->b_bufp) {
int c ;
line_p lp ;
long nbytes ; /* # of bytes in current buffer */
long nlines ; /* # of lines in current buffer */
/* skip invisible buffers if iflag is false */
if (((bp->b_flag & BFINVS) != 0) && (iflag != TRUE))
continue;
do_layout( line, bp->b_mode) ;
cp1 = line ; /* Start at left edge */
char *cp1 = line ; /* Start at left edge */
/* output status of ACTIVE flag ('@' when the file has been read in) */
*cp1++ = (bp->b_active == TRUE) ? '@' : ' ' ;
@ -370,9 +366,10 @@ static int makelist( int iflag) {
*cp1 = ((bp->b_flag & BFCHG) != 0) ? '*' : ' ' ;
/* Buffer size */
nbytes = 0L; /* Count bytes in buf. */
nlines = 0 ;
for( lp = lforw( bp->b_linep) ; lp != bp->b_linep ; lp = lforw( lp)) {
long nbytes = 0L; /* Count bytes in buf. */
long nlines = 0 ;
for( line_p lp = lforw( bp->b_linep) ; lp != bp->b_linep ;
lp = lforw( lp)) {
nbytes += (long) llength(lp) + 1L;
nlines += 1 ;
}
@ -385,8 +382,8 @@ static int makelist( int iflag) {
*cp1++ = ' ' ;
/* Display buffer name */
cp2 = &bp->b_bname[ 0] ;
while ((c = *cp2++) != 0)
char *cp2 = &bp->b_bname[ 0] ;
while( (c = *cp2++) != 0)
*cp1++ = c;
/* Pad with spaces to max buffer name length */
@ -528,7 +525,6 @@ buffer_p bfind( const char *bname, boolean create_f, int flags) {
updates that are required. Return TRUE if everything looks good.
*/
int bclear( buffer_p bp) {
line_p lp ;
int s ;
if( (bp->b_flag & (BFINVS | BFCHG)) == BFCHG /* regular and changed */
@ -536,13 +532,28 @@ int bclear( buffer_p bp) {
return s ;
bp->b_flag &= ~BFCHG ; /* Not changed */
while( (lp = lforw( bp->b_linep)) != bp->b_linep)
lfree( lp) ;
line_p lp = bp->b_linep ;
if( lp->l_fp != lp) { /* non empty buffer */
/* turn line ring into a list and delete it */
lp->l_bp->l_fp = NULL ;
freelist( (list_p) lp->l_fp) ;
lp->l_fp = lp->l_bp = lp ;
/* Fix dots and marks */
bp->b_dotp = bp->b_linep ; /* Fix "." */
bp->b_doto = 0 ;
bp->b_markp = NULL ; /* Invalidate "mark" */
bp->b_marko = 0 ;
if( bp->b_nwnd) /* buffer is displayed */
for( window_p wp = wheadp ; wp ; wp = wp->w_wndp)
if( wp->w_bufp == bp) {
wp->w_linep = wp->w_dotp = lp ;
wp->w_doto = 0 ;
wp->w_markp = NULL ;
wp->w_marko = 0 ;
}
}
bp->b_dotp = bp->b_linep ; /* Fix "." */
bp->b_doto = 0 ;
bp->b_markp = NULL ; /* Invalidate "mark" */
bp->b_marko = 0 ;
return TRUE ;
}

View File

@ -1,17 +1,63 @@
/* defines.h -- */
/* defines.h -- customization based on gcc predefined macroes */
#ifndef __DEFINES_H__
#define __DEFINES_H__
/* Must define one of
USG | BSD
*/
#define USG 1
#define PKCODE 1
#define SCROLLCODE 1 /* scrolling code P.K. */
#define ENVFUNC 1
#if __unix__
# define UNIX 1
# if __NetBSD__
# define BSD 1
# define POSIX 1
# elif __linux__
# define USG 1
# define SVR4 1 /* locks */
# define POSIX 1
# else /* __CYGWIN__ */
# define USG 1
//# define POSIX 1
# endif
#else
# error Missing gcc predefined __unix__
#endif
#define NSTRING 128 /* # of bytes, string buffers */
#define TERMCAP 1 /* UNIX */
#define XONXOFF 1 /* UNIX */
#define VISMAC 0 /* update display during keyboard macros */
#define MSDOS 0
#define IBMPC MSDOS
#define COLOR MSDOS
#define FILOCK (SVR4 | BSD)
#define ENVFUNC 1 /* only two types so far (USG | BSD) */
#define PKCODE 1 /* include P.K. extensions, define always */
#define SCROLLCODE 1 /* scrolling code P.K. */
/* Dynamic RAM tracking and reporting redefinitions */
#define RAMSIZE 0 /* dynamic RAM memory usage tracking */
#if RAMSIZE
# define RAMSHOW 1 /* auto dynamic RAM reporting */
# include <stdlib.h> /* size_t */
void *allocate( size_t size) ;
void release( void *ptr) ;
# define malloc( sz) allocate(sz)
# define free( ptr) release( ptr)
#endif
/* end of defines.h */
/* De-allocate memory always on exit (if the operating system or main
program can not)
*/
#define CLEAN 0 /* de-alloc memory on exit */
#if CLEAN
# define exit(a) cexit(a)
void cexit( int status) ;
#endif
#endif
/* end of predefs.h */

562
display.c
View File

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

View File

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

View File

@ -19,7 +19,7 @@
-------------------------------------------------------------------------------
=> THE VERY BASICS
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
be active at once. Many WINDOWS may be active at once on the screen. All
@ -37,7 +37,7 @@ Beginning of file ..... Meta < End of file ........... Meta >
-------------------------------------------------------------------------------
=> FILE COMMANDS
Find file ............. ^X ^F Quick exit ............ Meta Z
View file ............. ^X ^V Exit emacs ............ ^X ^C
View file ............. ^X ^V Exit µEMACS ........... ^X ^C
Insert file ........... ^X ^I
Change file name ...... ^X N Filter buffer ......... ^X #
Save file ............. ^X ^D
@ -118,12 +118,12 @@ Query replace string .. Meta ^R :: Yes/no Y/N, replace rest !, cancel ^G.
-------------------------------------------------------------------------------
=> ACCESSING THE OPERATING SYSTEM
Quick exit ............ Meta Z :: Write out all changed buffers and exit.
Exit emacs ............ ^X ^C :: Exit without automatic save.
Exit µEMACS ........... ^X ^C :: Exit without automatic save.
I shell ............... ^X C :: Start a new command processor.
Shell command ......... ^X ! :: Execute one operating system command.
Pipe command .......... ^X @ :: Pipe command results to a new buffer. *
Filter buffer ......... ^X # :: Filter buffer through a program. *
Execute program ....... ^X $ :: * Not under VMS.
Pipe command .......... ^X @ :: Pipe command results to a new buffer.
Filter buffer ......... ^X # :: Filter buffer through a program.
Execute program ....... ^X $ ::
-------------------------------------------------------------------------------
=> MACRO COMMANDS
Begin macro ........... ^X (

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.
;
; 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"
!force execute-file &cat $HOME "/.uerc"
set $tab 4
# set $viewtab TRUE # uncomment this line if you need to visualize tabs
set $fillcol 76
## Help facility
!if &seq $TERM cygwin
set $scroll FALSE
set %F1 FNP #currently not readable
set %Home FN1
set %End FN4
!else
; First, try to resolve if we are on a PC ... yes, this is a kludge
!if &seq $sres "NORMAL"
set %system "OTHER"
!else
set %system "PC"
set %F1 FNP
set %Home FNH
set %End FNF
!endif
!if &seq %system "PC"
; PC specific initialization
write-message "(Setting up)"
; Comment out or change this line if you want more than 25 lines,
; other possible $sres values include EGA and VGA
set $sres "CGA"
; Uncomment next line if your old screen "snows"
;set $flicker "TRUE"
; If your screen "snows" you'll not like scrolling
!if &seq $flicker "TRUE"
set $scroll "FALSE"
!endif
; Function keys (unshifted)
; f1 f2 f3 f4 f5 f6 f7 f8 f9 f10
; FN; FN< FN= FN> FN? FN@ FNA FNB FNC FND
bind-to-key help FN;
bind-to-key exit-emacs FND
; Function keys (shifted)
; F1 F2 F3 F4 F5 F6 F7 F8 F9 F10
; FNT FNU FNV FNW FNX FNY FNZ FN[ FN\ FN]
; Other special keys (unshifted)
; Home End Ins Del PgUp PgDn
; FNG FNO FNR FNS FNI FNQ
; Some common Alt-keys
; Alt-X Alt-Z Alt-C Alt-F Alt-O
; FN- FN, FN. FN! FN^X
bind-to-key exit-emacs FN-
bind-to-key quick-exit FN,
bind-to-key i-shell FN.
bind-to-key find-file FN!
bind-to-key view-file FN/
bind-to-key next-window FN^X
; Set screen colors
; You can define a DOS environment variable EMACS_BW (any value)
; if you don't like colors, e.g. if you have a LCD screen
!if &seq &env "EMACS_BW" ""
add-global-mode "blue"
add-global-mode "HIGH"
!endif
!endif
; Help facility
40 store-macro
set $discmd "FALSE"
!store 40
set $discmd FALSE
!if &not &seq $cbufname "emacs.hlp"
write-message "(Loading Help)"
!force help
!force 8 resize-window
!if &seq %system "PC"
!if &seq &env "EMACS_BW" ""
add-mode "red"
!endif
bind-to-key execute-macro-38 FNI
bind-to-key execute-macro-37 FNQ
!if &not &seq $cbufname "emacs.hlp"
write-message "(Failed to load Help)"
!else
bind-to-key execute-macro-38 FN5
bind-to-key execute-macro-37 FN6
!force 8 resize-window
bind-to-key execute-macro-39 FN5
bind-to-key execute-macro-38 FN6
bind-to-key execute-macro-37 %Home
bind-to-key execute-macro-36 %End
beginning-of-line
2 forward-character
1 redraw-display
set %hlpupdn "[PgUp] / [PgDn]"
set %hlphelp "[F1]"
run helponhelp
!endif
beginning-of-line
2 forward-character
1 redraw-display
save-window
!if &seq %system "PC"
set %hlpupdn "<PgUp> / <PgDn>"
set %hlphelp "<F1>"
!else
set %hlpupdn "<Prev Scrn> / <Next Scrn>"
set %hlphelp "<Help>"
!endif
execute-macro-39
!else
set %hlpcode &lef $line 2
!if &seq %hlpcode ".."
@ -117,33 +55,29 @@ bind-to-key next-window FN^X
beginning-of-line
2 forward-character
1 redraw-display
execute-macro-39
run helponhelp
!else
!if &seq %system "PC"
bind-to-key previous-page FNI
bind-to-key next-page FNQ
!else
bind-to-key previous-page FN5
bind-to-key next-page FN6
!endif
!force restore-window
!force search-reverse "=>"
bind-to-key previous-page FN5
bind-to-key next-page FN6
bind-to-key beginning-of-file %Home
bind-to-key end-of-file %End
!force delete-window
clear-message-line
!endif
!endif
set $discmd "TRUE"
set $discmd TRUE
!endm
bind-to-key execute-macro-40 M-?
!if &seq %system "PC"
bind-to-key execute-macro-40 FN;
!else
bind-to-key execute-macro-40 FNh
!endif
bind-to-key execute-macro-40 %F1
bind-to-key execute-macro-40 M-O
bind-to-key beginning-of-file %Home
bind-to-key end-of-file %End
; Help on Help
39 store-macro
## Help on Help
!store helponhelp
!if &seq &rig $line 5 "INDEX"
write-message &cat "Select topic from list and press " %hlphelp
!else
@ -151,150 +85,72 @@ bind-to-key execute-macro-40 M-?
!endif
!endm
; Previous help page
38 store-macro
## Previous help page
!store 39
!if &seq $cbufname "emacs.hlp"
beginning-of-line
!force search-reverse "=>"
2 forward-character
1 redraw-display
execute-macro-39
run helponhelp
!else
previous-page
!endif
!endm
; Next help page
37 store-macro
## Next help page
!store 38
!if &seq $cbufname "emacs.hlp"
beginning-of-line
2 forward-character
!force search-forward "=>"
1 redraw-display
execute-macro-39
run helponhelp
!else
next-page
!endif
!endm
; Set up auto CMODE
!store 37
beginning-of-file
!if &seq $cbufname "emacs.hlp"
execute-macro-39
!endif
!endm
36 store-macro
!if &seq &mid $cfname 1 7 "/tmp/Re"
add-mode "wrap"
!return
!endif
!if &gre &sin $cfname "/.ed" 0
add-mode "wrap"
!return
!endif
!if &gre &sin $cfname "/.let" 0
add-mode "wrap"
!return
!endif
!if &gre &sin $cfname "/.art" 0
add-mode "wrap"
!return
!endif
!if &gre &sin $cfname "/nn." 0
add-mode "wrap"
!return
!endif
set %rctmp &sin $cfname "."
!if &equ %rctmp 0
!return
!endif
set %rctmp &mid $cfname &add %rctmp 1 5
!if &or &seq %rctmp "c" &seq %rctmp "h"
add-mode "cmode"
!endif
!if &or &seq %rctmp "txt" &or &seq %rctmp "doc" &or &seq %rctmp "tmp" &seq %rctmp "tex"
add-mode "wrap"
!store 36
end-of-file
!if &seq $cbufname "emacs.hlp"
execute-macro-39
!endif
!endm
## Set up auto CMODE or WRAP
!store 35
set %rctmp &right $cfname 4
!if &or &seq .txt %rctmp &seq .doc %rctmp
add-mode wrap
!return
!endif
set %rctmp &right %rctmp 2
!if &or &seq .c %rctmp &seq .h %rctmp
add-mode cmode
!return
!endif
!endm
bind-to-key execute-macro-36 M-FNR
bind-to-key execute-macro-35 M-FNR
; Setup for ASCII {|}[\] to ISO Latin-1 translation
21 store-macro
insert-string "ä"
!endm
22 store-macro
insert-string "ö"
!endm
23 store-macro
insert-string "å"
!endm
24 store-macro
insert-string "Ä"
!endm
25 store-macro
insert-string "Ö"
!endm
26 store-macro
insert-string "Å"
!endm
27 store-macro
bind-to-key execute-macro-21 {
bind-to-key execute-macro-22 |
bind-to-key execute-macro-23 }
bind-to-key execute-macro-24 [
bind-to-key execute-macro-25 \
bind-to-key execute-macro-26 ]
write-message "ISO Latin-1 äöåÄÖÅ"
!endm
28 store-macro
unbind-key {
unbind-key |
unbind-key }
unbind-key [
unbind-key \
unbind-key ]
write-message "ASCII {|}[\]"
!endm
bind-to-key execute-macro-27 ^X[
bind-to-key execute-macro-28 ^X]
; Make cut-paste easier in window systems
## Make cut-paste easier in window systems
bind-to-key newline ^J
; uEmacs/PK specific initialization
!if &seq $progname "uEmacs/PK"
; Don't scroll on a Sun
!if &or &seq $TERM "sun" &seq $TERM "sun-cmd"
set $scroll "FALSE"
!endif
; Execute local initialization files
!if &seq %system "PC"
!force execute-file "EM.RC"
!else
!force execute-file &cat $HOME "/.emrc"
!force execute-file ".emrc"
!endif
!endif
!if &gre &sin $LANG "UTF-8" 0
!if &or &sin $LANG "UTF-8" &sin $LANG "utf8"
add-global-mode "utf-8"
!endif
!if &gre &sin $LANG "utf8" 0
add-global-mode "utf-8"
!endif
add-global-mode "utf-8"
!endif
set $discmd "TRUE"
set $discmd TRUE

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

2
eval.h
View File

@ -12,7 +12,7 @@
extern int macbug ; /* macro debuging flag */
extern int cmdstatus ; /* last command status */
extern int rval ; /* return value of a subprocess */
extern long envram ; /* # of bytes current in use by malloc */
extern unsigned envram ; /* # of bytes current in use by malloc */
int readfirst_f( void) ;
int is_it_cmd( char *token) ;

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) ;
/* Bindable functions */
BINDABLE( execbuf) ;
BINDABLE( execcmd) ;
BINDABLE( execfile) ;
BINDABLE( execproc) ;
BINDABLE( namedcmd) ;
BINDABLE( storemac) ;
BINDABLE( storeproc) ;
BINDABLE( execbuf) ;
BINDABLE( execcmd) ;
BINDABLE( execfile) ;
BINDABLE( execproc) ;
BINDABLE( namedcmd) ;
BBINDABLE( storemac) ;
BINDABLE( storeproc) ;
BINDABLE( cbuf1) ;
BINDABLE( cbuf2) ;
BINDABLE( cbuf3) ;

View File

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

1
file.c
View File

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

View File

@ -1,35 +1,16 @@
## floodmaz.cmd -- solve maze by painting wall on the right
# 6 set $seed
execute-file maze.cmd
# either maze.cmd or sharpmaz.cmd
execute-file sharpmaz.cmd
set %thisbuf $cbufname
store-procedure pushxy # push x y
set %x $curcol
set %y $curline
select-buffer stack
beginning-of-file
insert-string %x
newline
insert-string %y
newline
select-buffer %thisbuf
!endm
store-procedure popxy # pop x y
select-buffer stack
beginning-of-file
set %x $line
1 kill-to-end-of-line
set %y $line
1 kill-to-end-of-line
select-buffer %thisbuf
set $curline %y
set $curcol %x
!endm
set %meml $curline
set %memc $curcol
set $curline 1
set $curcol 0
run pushxy #push stop position
!gosub pushxy #push stop position
set %x 1
set $curline 4
set $curcol %x
@ -40,29 +21,47 @@ set %NC &asc "█"
set %cc $curcol
set %ll $curline
set $curcol &add %cc 1
!if &equ $curchar %OC
run pushxy
!endif
!gosub probe
set $curcol &add %cc -1
!if &equ $curchar %OC
run pushxy
!endif
!gosub probe
set $curline &add %ll 1
set $curcol %cc
!if &equ $curchar %OC
run pushxy
!endif
!gosub probe
set $curline &add %ll -1
set $curcol %cc
!if &equ $curchar %OC
run pushxy
!endif
run popxy
!gosub probe
# pop x y
select-buffer stack
beginning-of-file
set %x $line
1 kill-to-end-of-line
set %y $line
1 kill-to-end-of-line
select-buffer %thisbuf
set $curline %y
set $curcol %x
!endwhile
set $curline 3
set $curcol 1
set $curline %meml
set $curcol %memc
select-buffer stack
unmark-buffer
select-buffer %thisbuf
unmark-buffer
delete-buffer stack
!return
:probe
!if &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 "bind.h"
#include "estruct.h"
#include "bindable.h"
#include "defines.h"
#include "display.h" /* rubout(), echos(), echoc(), update() */
#include "exec.h"
#include "isa.h"

View File

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

758
line.c
View File

@ -20,7 +20,8 @@
#include <string.h>
#include "buffer.h"
#include "estruct.h"
#include "defines.h"
#include "list.h"
#include "mlout.h"
#include "utf8.h"
#include "window.h"
@ -37,58 +38,46 @@ static int ldelnewline( void) ;
* was taken up by the keycode structure).
*/
#define KBLOCK 250 /* sizeof kill buffer chunks */
#define KBLOCK 248 /* sizeof kill buffer chunks */
typedef struct kill {
struct kill *d_next; /* Link to next chunk, NULL if last. */
char d_chunk[KBLOCK]; /* Deleted text. */
struct kill *d_next ; /* Link to next chunk, NULL if last. */
char d_chunk[ KBLOCK] ; /* Deleted text. */
} *kill_p ;
static kill_p kbufp = NULL ; /* current kill buffer chunk pointer */
static kill_p kbufh = NULL ; /* kill buffer header pointer */
static int kused = KBLOCK ; /* # of bytes used in kill buffer */
static int klen ; /* length of kill buffer content */
static char *value = NULL ; /* temp buffer for value */
static int klen ; /* length of kill buffer content */
static char *value = NULL ; /* temp buffer for value */
/*
* return some of the contents of the kill buffer
*/
char *getkill( void) {
kill_p kp ;
char *cp ;
if (kbufh == NULL)
/* no kill buffer....just a null string */
const char *getkill( void) {
/* no kill buffer or no memory .... just return a null string */
if( kbufh == NULL
|| (value = realloc( value, klen + 1)) == NULL)
return "" ;
if( value != NULL)
free( value) ;
value = (char *) malloc( klen + 1) ;
cp = value ;
for( kp = kbufh ; kp != NULL ; kp = kp->d_next) {
int size ;
if( kp->d_next != NULL)
size = KBLOCK ;
else
size = kused ;
char *cp = value ;
for( kill_p kp = kbufh ; kp != NULL ; kp = kp->d_next) {
int size = (kp->d_next != NULL) ? KBLOCK : kused ;
memcpy( cp, kp->d_chunk, size) ;
cp += size ;
}
*cp = 0 ;
/* and return the constructed value */
return value;
/* and return the constructed value */
return value ;
}
/* Move the cursor backwards by "n" characters. If "n" is less than zero
call "forwchar" to actually do the move. Otherwise compute the new
cursor location. Error if you try and move out of the buffer. Set the
flag if the line pointer for dot changes.
/* Move the cursor backwards by "n" combined characters. If "n" is less
than zero call "forwchar" to actually do the move. Otherwise compute
the new cursor location. Error if you try and move out of the buffer.
Set the flag if the line pointer for dot changes.
*/
BBINDABLE( backchar) {
assert( f == TRUE || n == 1) ;
@ -105,9 +94,26 @@ BBINDABLE( backchar) {
curwp->w_doto = llength( lp) ;
curwp->w_flag |= WFMOVE ;
} else {
unsigned pos = curwp->w_doto -= 1 ;
if( pos > 0)
curwp->w_doto -= utf8_revdelta( (unsigned char *) &( (curwp->w_dotp)->l_text[ pos]), pos) ;
unsigned pos ;
/* move back over combining unicode */
combined:
pos = curwp->w_doto -= 1 ;
/* check if at end of unicode */
if( pos > 0) {
unsigned delta = utf8_revdelta(
(unsigned char *) &( (curwp->w_dotp)->l_text[ pos]), pos) ;
if( delta != 0) {
pos = curwp->w_doto -= delta ;
if( pos > 0) { /* check if on combining unicode */
unicode_t unc ;
utf8_to_unicode( curwp->w_dotp->l_text, pos,
llength( curwp->w_dotp), &unc) ;
if( utf8_width( unc) == 0)
goto combined ;
}
}
}
}
}
@ -115,10 +121,11 @@ BBINDABLE( backchar) {
}
/* Move the cursor forwards by "n" characters. If "n" is less than zero
call "backchar" to actually do the move. Otherwise compute the new
cursor location, and move ".". Error if you try and move off the end of
the buffer. Set the flag if the line pointer for dot changes.
/* Move the cursor forwards by "n" combined characters. If "n" is less
than zero call "backchar" to actually do the move. Otherwise compute
the new cursor location, and move ".". Error if you try and move off
the end of the buffer. Set the flag if the line pointer for dot
changes.
*/
BBINDABLE( forwchar) {
assert( f == TRUE || n == 1) ;
@ -140,7 +147,7 @@ BBINDABLE( forwchar) {
curwp->w_doto += utf8_to_unicode( curwp->w_dotp->l_text,
curwp->w_doto, len, &unc) ;
/* check if next char is null width unicode */
while( curwp->w_doto != len) {
while( curwp->w_doto < len - 1) {
unsigned bytes = utf8_to_unicode( curwp->w_dotp->l_text,
curwp->w_doto, len, &unc) ;
if( utf8_width( unc) == 0)
@ -154,8 +161,8 @@ BBINDABLE( forwchar) {
return TRUE ;
}
/*
* This routine allocates a block of memory large enough to hold a struct line
/* This routine allocates a block of memory large enough to hold a struct line
* containing "used" characters. The block is always rounded up a bit. Return
* a pointer to the new block, or NULL if there isn't any memory left. Print a
* message in the message line if no space.
@ -163,13 +170,13 @@ BBINDABLE( forwchar) {
line_p lalloc( int used) {
#define BLOCK_SIZE 16 /* Line block chunk size. */
/* rounding down use masking instead or modulo when BLOCK_SIZE is power of 2 */
/* rounding down use masking instead of modulo when BLOCK_SIZE is power of 2 */
#if (BLOCK_SIZE & -BLOCK_SIZE) == BLOCK_SIZE
int size = (used + BLOCK_SIZE) & ~(BLOCK_SIZE - 1) ;
#else
int size = used + BLOCK_SIZE - used % BLOCK_SIZE ;
#endif
line_p lp = (line_p) malloc( offsetof( struct line, l_text) + size) ;
line_p lp = malloc( sizeof *lp + size) ;
if( lp == NULL)
mloutstr( "(OUT OF MEMORY)") ;
else {
@ -180,76 +187,70 @@ line_p lalloc( int used) {
return lp ;
}
/*
* Delete line "lp". Fix all of the links that might point at it (they are
/* Delete line "lp". Fix all of the links that might point at it (they are
* moved to offset 0 of the next line. Unlink the line from whatever buffer it
* might be in. Release the memory. The buffers are updated too; the magic
* conditions described in the above comments don't hold here.
*/
void lfree( line_p lp) {
buffer_p bp;
struct window *wp;
for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
if( wp->w_linep == lp)
wp->w_linep = lp->l_fp ;
wp = wheadp;
while (wp != NULL) {
if (wp->w_linep == lp)
wp->w_linep = lp->l_fp;
if (wp->w_dotp == lp) {
wp->w_dotp = lp->l_fp;
wp->w_doto = 0;
if( wp->w_dotp == lp) {
wp->w_dotp = lp->l_fp ;
wp->w_doto = 0 ;
}
if (wp->w_markp == lp) {
wp->w_markp = lp->l_fp;
wp->w_marko = 0;
if( wp->w_markp == lp) {
wp->w_markp = lp->l_fp ;
wp->w_marko = 0 ;
}
wp = wp->w_wndp;
}
bp = bheadp;
while (bp != NULL) {
if (bp->b_nwnd == 0) {
if (bp->b_dotp == lp) {
bp->b_dotp = lp->l_fp;
bp->b_doto = 0;
for( buffer_p bp = bheadp ; bp != NULL ; bp = bp->b_bufp) {
if( bp->b_nwnd == 0) {
if( bp->b_dotp == lp) {
bp->b_dotp = lp->l_fp ;
bp->b_doto = 0 ;
}
if (bp->b_markp == lp) {
bp->b_markp = lp->l_fp;
bp->b_marko = 0;
if( bp->b_markp == lp) {
bp->b_markp = lp->l_fp ;
bp->b_marko = 0 ;
}
}
bp = bp->b_bufp;
}
lp->l_bp->l_fp = lp->l_fp;
lp->l_fp->l_bp = lp->l_bp;
free((char *) lp);
lp->l_bp->l_fp = lp->l_fp ;
lp->l_fp->l_bp = lp->l_bp ;
free( lp) ;
}
/*
* This routine gets called when a character is changed in place in the current
/* This routine gets called when a character is changed in place in the current
* buffer. It updates all of the required flags in the buffer and window
* system. The flag used is passed as an argument; if the buffer is being
* displayed in more than 1 window we change EDIT t HARD. Set MODE if the
* displayed in more than 1 window we change EDIT to HARD. Set MODE if the
* mode line needs to be updated (the "*" has to be set).
*/
void lchange(int flag)
{
struct window *wp;
void lchange( int flag) {
if( curbp->b_nwnd != 1) /* Ensure hard. */
flag = WFHARD ;
if (curbp->b_nwnd != 1) /* Ensure hard. */
flag = WFHARD;
if ((curbp->b_flag & BFCHG) == 0) { /* First change, so */
flag |= WFMODE; /* update mode lines. */
curbp->b_flag |= BFCHG;
}
wp = wheadp;
while (wp != NULL) {
if (wp->w_bufp == curbp)
wp->w_flag |= flag;
wp = wp->w_wndp;
if( (curbp->b_flag & BFCHG) == 0) { /* First change, so */
flag |= WFMODE ; /* update mode lines. */
curbp->b_flag |= BFCHG ;
}
for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp)
if( wp->w_bufp == curbp)
wp->w_flag |= flag ;
}
/*
* insert spaces forward into text
/* insert spaces forward into text
*
* int f, n; default flag and numeric argument
*/
@ -260,24 +261,18 @@ BINDABLE( insspace) {
return TRUE ;
}
/*
* linstr -- Insert a string at the current point
*/
int linstr( char *instr) {
int status = TRUE ;
/* linstr -- Insert a string at the current point */
boolean linstr( char *instr) {
boolean status = TRUE ;
if( instr != NULL) {
unicode_t tmpc ;
int c ;
while( (tmpc = *instr++ & 0xFF)) {
status =
(tmpc == '\n' ? lnewline() : (int) linsert_byte( 1, tmpc)) ;
/* Insertion error? */
if( status != TRUE) {
while( (c = (unsigned char) *instr++)) {
status = (c == '\n') ? lnewline() : linsert_byte( 1, c) ;
if( status != TRUE) { /* Insertion error? */
mloutstr( "%Out of memory while inserting") ;
return status ;
break ;
}
}
}
@ -298,84 +293,88 @@ int linstr( char *instr) {
boolean linsert_byte( int n, int c) {
char *cp1;
char *cp2;
line_p lp1, lp2, lp3 ;
int doto;
int i;
struct window *wp;
line_p lp2, lp3 ;
int i ;
assert( (curbp->b_mode & MDVIEW) == 0) ;
lchange(WFEDIT);
lp1 = curwp->w_dotp; /* Current line */
if (lp1 == curbp->b_linep) { /* At the end: special */
if (curwp->w_doto != 0) {
mloutstr( "bug: linsert") ;
return FALSE;
}
lchange( WFEDIT) ;
line_p lp1 = curwp->w_dotp ; /* Current line */
if( lp1 == curbp->b_linep) { /* At the end: special */
if( curwp->w_doto != 0)
return mloutfail( "bug: linsert") ;
lp2 = lalloc( n) ; /* Allocate new line */
if( lp2 == NULL)
return FALSE ;
lp3 = lp1->l_bp; /* Previous line */
lp3->l_fp = lp2; /* Link in */
lp2->l_fp = lp1;
lp1->l_bp = lp2;
lp2->l_bp = lp3;
for (i = 0; i < n; ++i)
lp2->l_text[i] = c;
curwp->w_dotp = lp2;
curwp->w_doto = n;
return TRUE;
lp3 = lp1->l_bp ; /* Previous line */
lp3->l_fp = lp2 ; /* Link in */
lp2->l_fp = lp1 ;
lp1->l_bp = lp2 ;
lp2->l_bp = lp3 ;
for( i = 0 ; i < n ; ++i)
lp2->l_text[ i] = c ;
curwp->w_dotp = lp2 ;
curwp->w_doto = n ;
return TRUE ;
}
doto = curwp->w_doto; /* Save for later. */
if (lp1->l_used + n > lp1->l_size) { /* Hard: reallocate */
int doto = curwp->w_doto ; /* Save for later. */
if( lp1->l_used + n > lp1->l_size) { /* Hard: reallocate */
lp2 = lalloc( lp1->l_used + n) ;
if( lp2 == NULL)
return FALSE ;
cp1 = &lp1->l_text[0];
cp2 = &lp2->l_text[0];
while (cp1 != &lp1->l_text[doto])
*cp2++ = *cp1++;
cp2 += n;
while (cp1 != &lp1->l_text[lp1->l_used])
*cp2++ = *cp1++;
lp1->l_bp->l_fp = lp2;
lp2->l_fp = lp1->l_fp;
lp1->l_fp->l_bp = lp2;
lp2->l_bp = lp1->l_bp;
free((char *) lp1);
cp1 = &lp1->l_text[ 0] ;
cp2 = &lp2->l_text[ 0] ;
while( cp1 != &lp1->l_text[ doto])
*cp2++ = *cp1++ ;
cp2 += n ;
while( cp1 != &lp1->l_text[ lp1->l_used])
*cp2++ = *cp1++ ;
lp1->l_bp->l_fp = lp2 ;
lp2->l_fp = lp1->l_fp ;
lp1->l_fp->l_bp = lp2 ;
lp2->l_bp = lp1->l_bp ;
free( lp1) ;
} else { /* Easy: in place */
lp2 = lp1; /* Pretend new line */
lp2->l_used += n;
cp2 = &lp1->l_text[lp1->l_used];
cp1 = cp2 - n;
while (cp1 != &lp1->l_text[doto])
*--cp2 = *--cp1;
lp2 = lp1 ; /* Pretend new line */
lp2->l_used += n ;
cp2 = &lp1->l_text[ lp1->l_used] ;
cp1 = cp2 - n ;
while( cp1 != &lp1->l_text[ doto])
*--cp2 = *--cp1 ;
}
for (i = 0; i < n; ++i) /* Add the characters */
lp2->l_text[doto + i] = c;
wp = wheadp; /* Update windows */
while (wp != NULL) {
if (wp->w_linep == lp1)
wp->w_linep = lp2;
if (wp->w_dotp == lp1) {
wp->w_dotp = lp2;
if (wp == curwp || wp->w_doto > doto)
wp->w_doto += n;
for( i = 0 ; i < n ; ++i) /* Add the characters */
lp2->l_text[ doto + i] = c ;
/* Update windows */
for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
if( wp->w_linep == lp1)
wp->w_linep = lp2 ;
if( wp->w_dotp == lp1) {
wp->w_dotp = lp2 ;
if( wp == curwp || wp->w_doto > doto)
wp->w_doto += n ;
}
if (wp->w_markp == lp1) {
wp->w_markp = lp2;
if (wp->w_marko > doto)
wp->w_marko += n;
if( wp->w_markp == lp1) {
wp->w_markp = lp2 ;
if( wp->w_marko > doto)
wp->w_marko += n ;
}
wp = wp->w_wndp;
}
return TRUE;
return TRUE ;
}
int linsert( int n, unicode_t c) {
boolean linsert( int n, unicode_t c) {
assert( n >= 0) ;
assert( !(curbp->b_mode & MDVIEW)) ;
@ -403,7 +402,7 @@ int linsert( int n, unicode_t c) {
*
* int c ; character to overwrite on current position
*/
static int lowrite( int c) {
static boolean lowrite( int c) {
if( curwp->w_doto < curwp->w_dotp->l_used
&& ( lgetc( curwp->w_dotp, curwp->w_doto) != '\t'
|| (curwp->w_doto % tabwidth) == (tabwidth - 1)
@ -413,20 +412,18 @@ static int lowrite( int c) {
return linsert( 1, c) ;
}
/*
* lover -- Overwrite a string at the current point
*/
int lover( char *ostr) {
int status = TRUE ;
/* lover -- Overwrite a string at the current point */
boolean lover( char *ostr) {
boolean status = TRUE ;
if( ostr != NULL) {
char tmpc ;
int c ;
while( (tmpc = *ostr++)) {
status = (tmpc == '\n' ? lnewline() : lowrite( tmpc)) ;
while( (c = (unsigned char) *ostr++)) {
status = (c == '\n') ? lnewline() : lowrite( c) ;
if( status != TRUE) { /* Insertion error? */
mloutstr( "%Out of memory while overwriting") ;
return status ;
break ;
}
}
}
@ -434,21 +431,15 @@ int lover( char *ostr) {
return status ;
}
/*
* Insert a newline into the buffer at the current location of dot in the
* current window. The funny ass-backwards way it does things is not a botch;
* it just makes the last line in the file not a special case. Return TRUE if
* everything works out and FALSE on error (memory allocation failure). The
* update of dot and mark is a bit easier then in the above case, because the
* split forces more updating.
*/
int lnewline( void) {
char *cp1;
char *cp2;
line_p lp1, lp2 ;
int doto;
struct window *wp;
/* Insert a newline into the buffer at the current location of dot in the
current window. The funny ass-backwards way it does things is not a
botch; it just makes the last line in the file not a special case.
Return TRUE if everything works out and FALSE on error (memory
allocation failure). The update of dot and mark is a bit easier then in
the above case, because the split forces more updating.
*/
boolean lnewline( void) {
assert( !(curbp->b_mode & MDVIEW)) ;
#if SCROLLCODE
@ -456,75 +447,104 @@ int lnewline( void) {
#else
lchange(WFHARD);
#endif
lp1 = curwp->w_dotp; /* Get the address and */
doto = curwp->w_doto; /* offset of "." */
lp2 = lalloc( doto) ; /* New first half line */
line_p lp1 = curwp->w_dotp ; /* Get the address and */
int doto = curwp->w_doto ; /* offset of "." */
line_p lp2 = lalloc( doto) ; /* New first half line */
if( lp2 == NULL)
return FALSE ;
cp1 = &lp1->l_text[0]; /* Shuffle text around */
cp2 = &lp2->l_text[0];
while (cp1 != &lp1->l_text[doto])
*cp2++ = *cp1++;
cp2 = &lp1->l_text[0];
while (cp1 != &lp1->l_text[lp1->l_used])
*cp2++ = *cp1++;
lp1->l_used -= doto;
lp2->l_bp = lp1->l_bp;
lp1->l_bp = lp2;
lp2->l_bp->l_fp = lp2;
lp2->l_fp = lp1;
wp = wheadp; /* Windows */
while (wp != NULL) {
if (wp->w_linep == lp1)
wp->w_linep = lp2;
if (wp->w_dotp == lp1) {
if (wp->w_doto < doto)
wp->w_dotp = lp2;
memcpy( lp2->l_text, lp1->l_text, doto) ;
lp1->l_used -= doto ;
memcpy( lp1->l_text, &lp1->l_text[ doto], lp1->l_used) ;
lp2->l_fp = lp1 ;
lp2->l_bp = lp1->l_bp ;
lp1->l_bp = lp2 ;
lp2->l_bp->l_fp = lp2 ;
for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
if( wp->w_linep == lp1)
wp->w_linep = lp2 ;
if( wp->w_dotp == lp1) {
if( wp->w_doto < doto)
wp->w_dotp = lp2 ;
else
wp->w_doto -= doto;
wp->w_doto -= doto ;
}
if (wp->w_markp == lp1) {
if (wp->w_marko < doto)
wp->w_markp = lp2;
if( wp->w_marko < doto)
wp->w_markp = lp2 ;
else
wp->w_marko -= doto;
wp->w_marko -= doto ;
}
wp = wp->w_wndp;
}
return TRUE;
return TRUE ;
}
int lgetchar( unicode_t *c) {
if( curwp->w_dotp->l_used == curwp->w_doto) {
*c = (curbp->b_mode & MDDOS) ? '\r' : '\n' ;
/* lgetchar():
* get unicode value and return UTF-8 size of character at dot.
*/
int lgetchar( unicode_t *cp) {
if( curwp->w_dotp->l_used == curwp->w_doto) { /* at EOL? */
*cp = (curbp->b_mode & MDDOS) ? '\r' : '\n' ;
return 1 ;
} else
return utf8_to_unicode( curwp->w_dotp->l_text, curwp->w_doto,
llength( curwp->w_dotp), c) ;
llength( curwp->w_dotp), cp) ;
}
/*
/* lcombinedsize():
* return total UTF-8 size of combined character at dot.
*/
static int lcombinedsize( void) {
if( curwp->w_dotp->l_used == curwp->w_doto) /* EOL? */
return 1 ;
else {
unicode_t c ;
int pos = curwp->w_doto ;
unsigned bytes = utf8_to_unicode( curwp->w_dotp->l_text, pos,
llength( curwp->w_dotp), &c) ;
/* check if followed by combining unicode character */
pos += bytes ;
while( pos < llength( curwp->w_dotp) - 1) { /* at least 2 bytes */
unsigned cnt = utf8_to_unicode( curwp->w_dotp->l_text, pos,
llength( curwp->w_dotp), &c) ;
if( utf8_width( c) == 0) {
bytes += cnt ;
pos += cnt ;
} else
break ;
}
return bytes ;
}
}
/* ldelchar():
* delete forward combined characters starting at dot.
*
* ldelete() really fundamentally works on bytes, not characters.
* It is used for things like "scan 5 words forwards, and remove
* the bytes we scanned".
*
* If you want to delete characters, use ldelchar().
*/
boolean ldelchar( long n, boolean kflag) {
boolean ldelchar( long n, boolean kill_f) {
/* testing for read only mode is done by ldelete() */
while( n-- > 0) {
unicode_t c;
if( !ldelete( lgetchar( &c), kflag))
while( n-- > 0)
if( !ldelete( lcombinedsize(), kill_f))
return FALSE ;
}
return TRUE ;
}
/*
* This function deletes "n" bytes, starting at dot. It understands how do deal
/* This function deletes "n" bytes, starting at dot. It understands how do deal
* with end of lines, etc. It returns TRUE if all of the characters were
* deleted, and FALSE if they were not (because dot ran into the end of the
* buffer. The "kflag" is TRUE if the text should be put in the kill buffer.
@ -533,101 +553,72 @@ boolean ldelchar( long n, boolean kflag) {
* int kflag; put killed text in kill buffer flag
*/
boolean ldelete( long n, boolean kflag) {
char *cp1;
char *cp2;
line_p dotp;
int doto;
int chunk;
struct window *wp;
assert( !(curbp->b_mode & MDVIEW)) ;
while( n > 0) {
dotp = curwp->w_dotp;
doto = curwp->w_doto;
if (dotp == curbp->b_linep) /* Hit end of buffer. */
return FALSE;
chunk = dotp->l_used - doto; /* Size of chunk. */
if (chunk > n)
chunk = n;
if (chunk == 0) { /* End of line, merge. */
line_p dotp = curwp->w_dotp ;
if( dotp == curbp->b_linep) /* Hit end of buffer. */
return FALSE ;
int doto = curwp->w_doto ;
int chunk = dotp->l_used - doto ; /* Size of chunk. */
if( chunk == 0) { /* End of line, merge. */
#if SCROLLCODE
lchange(WFHARD | WFKILLS);
lchange( WFHARD | WFKILLS) ;
#else
lchange(WFHARD);
lchange( WFHARD) ;
#endif
if (ldelnewline() == FALSE
|| (kflag != FALSE && kinsert('\n') == FALSE))
return FALSE;
--n;
continue;
}
lchange(WFEDIT);
cp1 = &dotp->l_text[doto]; /* Scrunch text. */
cp2 = cp1 + chunk;
if (kflag != FALSE) { /* Kill? */
while (cp1 != cp2) {
if (kinsert(*cp1) == FALSE)
return FALSE;
++cp1;
}
cp1 = &dotp->l_text[doto];
}
while (cp2 != &dotp->l_text[dotp->l_used])
*cp1++ = *cp2++;
dotp->l_used -= chunk;
wp = wheadp; /* Fix windows */
while (wp != NULL) {
if (wp->w_dotp == dotp && wp->w_doto >= doto) {
wp->w_doto -= chunk;
if (wp->w_doto < doto)
wp->w_doto = doto;
}
if (wp->w_markp == dotp && wp->w_marko >= doto) {
wp->w_marko -= chunk;
if (wp->w_marko < doto)
wp->w_marko = doto;
}
wp = wp->w_wndp;
}
n -= chunk;
}
return TRUE;
}
if( ldelnewline() == FALSE
|| (kflag != FALSE && kinsert( '\n') == FALSE))
return FALSE ;
/*
* getctext: grab and return a string with the text of
* the current line
*/
char *getctext( void) {
line_p lp ; /* line to copy */
int size; /* length of line to return */
static int rsize = 0 ;
static char *rline ; /* line to return */
--n ;
continue ;
} else if( chunk > n)
chunk = n ;
/* find the contents of the current line and its length */
lp = curwp->w_dotp;
size = lp->l_used;
if( size >= rsize) {
if( rsize)
free( rline) ;
lchange( WFEDIT) ;
char *cp1 = &dotp->l_text[ doto] ; /* Scrunch text. */
char *cp2 = cp1 + chunk ;
if( kflag != FALSE) { /* Kill? */
while( cp1 != cp2) {
if( kinsert( *cp1) == FALSE)
return FALSE ;
++cp1 ;
}
rsize = size + 1 ;
rline = malloc( rsize) ;
if( rline == NULL) {
rsize = 0 ;
return "" ;
cp1 = &dotp->l_text[ doto] ;
}
while( cp2 != &dotp->l_text[ dotp->l_used])
*cp1++ = *cp2++ ;
dotp->l_used -= chunk ;
/* Fix windows */
for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
if( wp->w_dotp == dotp && wp->w_doto >= doto) {
wp->w_doto -= chunk ;
if( wp->w_doto < doto)
wp->w_doto = doto ;
}
if( wp->w_markp == dotp && wp->w_marko >= doto) {
wp->w_marko -= chunk ;
if( wp->w_marko < doto)
wp->w_marko = doto ;
}
}
n -= chunk ;
}
/* copy it across */
memcpy( rline, lp->l_text, size) ;
rline[ size] = 0 ;
return rline ;
return TRUE ;
}
/*
* Delete a newline. Join the current line with the next line. If the next line
/* Delete a newline. Join the current line with the next line. If the next line
* is the magic header line always return TRUE; merging the last line with the
* header line can be thought of as always being a successful operation, even
* if nothing is done, and this makes the kill buffer work "right". Easy cases
@ -638,104 +629,101 @@ char *getctext( void) {
static int ldelnewline( void) {
char *cp1;
char *cp2;
line_p lp1, lp2, lp3 ;
struct window *wp;
window_p wp ;
assert( (curbp->b_mode & MDVIEW) == 0) ;
lp1 = curwp->w_dotp;
lp2 = lp1->l_fp;
if (lp2 == curbp->b_linep) { /* At the buffer end. */
if (lp1->l_used == 0) /* Blank line. */
lfree(lp1);
return TRUE;
line_p lp1 = curwp->w_dotp ;
line_p lp2 = lp1->l_fp ;
if( lp2 == curbp->b_linep) { /* At the buffer end. */
if( lp1->l_used == 0) /* Blank line. */
lfree( lp1) ;
return TRUE ;
}
if (lp2->l_used <= lp1->l_size - lp1->l_used) {
cp1 = &lp1->l_text[lp1->l_used];
cp2 = &lp2->l_text[0];
while (cp2 != &lp2->l_text[lp2->l_used])
*cp1++ = *cp2++;
wp = wheadp;
while (wp != NULL) {
if (wp->w_linep == lp2)
wp->w_linep = lp1;
if (wp->w_dotp == lp2) {
wp->w_dotp = lp1;
wp->w_doto += lp1->l_used;
if( lp2->l_used <= lp1->l_size - lp1->l_used) {
cp1 = &lp1->l_text[ lp1->l_used] ;
cp2 = lp2->l_text ;
while( cp2 != &lp2->l_text[ lp2->l_used])
*cp1++ = *cp2++ ;
for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
if( wp->w_linep == lp2)
wp->w_linep = lp1 ;
if( wp->w_dotp == lp2) {
wp->w_dotp = lp1 ;
wp->w_doto += lp1->l_used ;
}
if (wp->w_markp == lp2) {
wp->w_markp = lp1;
wp->w_marko += lp1->l_used;
if( wp->w_markp == lp2) {
wp->w_markp = lp1 ;
wp->w_marko += lp1->l_used ;
}
wp = wp->w_wndp;
}
lp1->l_used += lp2->l_used;
lp1->l_fp = lp2->l_fp;
lp2->l_fp->l_bp = lp1;
free((char *) lp2);
return TRUE;
lp1->l_used += lp2->l_used ;
lp1->l_fp = lp2->l_fp ;
lp2->l_fp->l_bp = lp1 ;
free( lp2) ;
return TRUE ;
}
lp3 = lalloc( lp1->l_used + lp2->l_used) ;
line_p lp3 = lalloc( lp1->l_used + lp2->l_used) ;
if( lp3 == NULL)
return FALSE ;
cp1 = &lp1->l_text[0];
cp2 = &lp3->l_text[0];
while (cp1 != &lp1->l_text[lp1->l_used])
*cp2++ = *cp1++;
cp1 = &lp2->l_text[0];
while (cp1 != &lp2->l_text[lp2->l_used])
*cp2++ = *cp1++;
lp1->l_bp->l_fp = lp3;
lp3->l_fp = lp2->l_fp;
lp2->l_fp->l_bp = lp3;
lp3->l_bp = lp1->l_bp;
wp = wheadp;
while (wp != NULL) {
if (wp->w_linep == lp1 || wp->w_linep == lp2)
wp->w_linep = lp3;
if (wp->w_dotp == lp1)
wp->w_dotp = lp3;
else if (wp->w_dotp == lp2) {
wp->w_dotp = lp3;
wp->w_doto += lp1->l_used;
cp1 = lp1->l_text ;
cp2 = lp3->l_text ;
while( cp1 != &lp1->l_text[ lp1->l_used])
*cp2++ = *cp1++ ;
cp1 = lp2->l_text ;
while( cp1 != &lp2->l_text[ lp2->l_used])
*cp2++ = *cp1++ ;
lp1->l_bp->l_fp = lp3 ;
lp3->l_fp = lp2->l_fp ;
lp2->l_fp->l_bp = lp3 ;
lp3->l_bp = lp1->l_bp ;
for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
if( wp->w_linep == lp1 || wp->w_linep == lp2)
wp->w_linep = lp3 ;
if( wp->w_dotp == lp1)
wp->w_dotp = lp3 ;
else if( wp->w_dotp == lp2) {
wp->w_dotp = lp3 ;
wp->w_doto += lp1->l_used ;
}
if (wp->w_markp == lp1)
wp->w_markp = lp3;
else if (wp->w_markp == lp2) {
wp->w_markp = lp3;
wp->w_marko += lp1->l_used;
if( wp->w_markp == lp1)
wp->w_markp = lp3 ;
else if( wp->w_markp == lp2) {
wp->w_markp = lp3 ;
wp->w_marko += lp1->l_used ;
}
wp = wp->w_wndp;
}
free((char *) lp1);
free((char *) lp2);
return TRUE;
free( lp1) ;
free( lp2) ;
return TRUE ;
}
/*
* Delete all of the text saved in the kill buffer. Called by commands when a
/* Delete all of the text saved in the kill buffer. Called by commands when a
* new kill context is being created. The kill buffer array is released, just
* in case the buffer has grown to immense size. No errors.
*/
void kdelete(void)
{
kill_p kp; /* ptr to scan kill buffer chunk list */
void kdelete( void) {
if( kbufh != NULL) {
/* first, delete all the chunks */
freelist( (list_p) kbufh) ;
if (kbufh != NULL) {
/* first, delete all the chunks */
kbufp = kbufh;
while (kbufp != NULL) {
kp = kbufp->d_next;
free(kbufp);
kbufp = kp;
}
/* and reset all the kill buffer pointers */
kbufh = kbufp = NULL;
kused = KBLOCK;
/* and reset all the kill buffer pointers */
kbufh = kbufp = NULL ;
kused = KBLOCK ;
klen = 0 ;
if( value != NULL) {
free( value) ;

26
line.h
View File

@ -14,11 +14,11 @@
list of marks into the line.
*/
typedef struct line {
struct line *l_fp ; /* Forward link to the next line */
struct line *l_bp ; /* Backward link to the previous line */
int l_size ; /* Allocated size */
int l_used ; /* Used size */
char l_text[ 1] ; /* A bunch of characters */
struct line *l_fp ; /* Forward link to the next line */
struct line *l_bp ; /* Backward link to the previous line */
int l_size ; /* Allocated size */
int l_used ; /* Used size */
char l_text[] ; /* A bunch of characters */
} *line_p ;
#define lforw(lp) ((lp)->l_fp)
@ -29,28 +29,26 @@ typedef struct line {
extern int tabwidth ; /* Map to $tab, default to 8, can be set to [1, .. */
char *getkill( void) ;
/* Bindable functions */
BBINDABLE( backchar) ;
BBINDABLE( forwchar) ;
BINDABLE( insspace) ;
BINDABLE( yank) ;
void lfree( line_p lp) ;
void lchange( int flag) ;
int linstr( char *instr) ;
int linsert( int n, unicode_t c) ;
boolean linstr( char *instr) ;
boolean linsert( int n, unicode_t c) ;
boolean linsert_byte( int n, int c) ;
int lover( char *ostr) ;
int lnewline( void) ;
boolean lover( char *ostr) ;
boolean lnewline( void) ;
boolean ldelete( long n, boolean kflag) ;
boolean ldelchar( long n, boolean kflag) ;
int lgetchar( unicode_t *cref) ;
char *getctext( void) ;
void kdelete( void) ;
int kinsert( int c) ;
line_p lalloc( int minsize) ; /* Allocate a line of at least minsize chars. */
line_p lalloc( int minsize) ; /* Allocate a line of at least minsize chars. */
void lfree( line_p lp) ; /* free a line, updating buffers and windows */
const char *getkill( void) ; /* get value of $kill */
boolean rdonly( void) ; /* Read Only error message */

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_
#define _LOCK_H_
#include "estruct.h"
#include "defines.h" /* BSD, SVR4 */
#if BSD | SVR4
int lockchk( const char *fname) ;

165
main.c
View File

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

View File

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

View File

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

View File

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

91
posix.c
View File

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

View File

@ -14,8 +14,8 @@
#include "basic.h"
#include "buffer.h"
#include "defines.h"
#include "display.h"
#include "estruct.h"
#include "execute.h"
#include "input.h"
#include "line.h"
@ -219,30 +219,31 @@ boolean setccol( int pos) {
*/
BBINDABLE( twiddle) {
unicode_t c ;
boolean eof_f = FALSE ;
assert( !(curbp->b_mode & MDVIEW)) ;
int len = llength( curwp->w_dotp) ;
if( len < 2 || curwp->w_doto == 0) /* at least 2 chars & not bol */
if( len < 2 || curwp->w_doto == 0) /* at least 2 bytes & not bol */
return FALSE ;
if( curwp->w_doto == len) { /* at end of line */
if( curwp->w_doto == len) { /* at end of line */
backchar( FALSE, 1) ;
eof_f = TRUE ;
if( curwp->w_doto == 0) {
/* only one combined character on this line */
forwchar( FALSE, 1) ;
return FALSE ;
}
}
len = lgetchar( &c) ; /* len => unicode or extended ASCII */
ldelchar( 1, FALSE) ;
backchar( FALSE, 1) ;
len = lgetchar( &c) ; /* len => unicode or extended ASCII */
ldelchar( 1, FALSE) ;
forwchar( FALSE, 1) ;
if( len == 1)
linsert_byte( 1, c) ;
else
linsert( 1, c) ;
if( eof_f == TRUE)
forwchar( FALSE, 1) ;
lchange( WFEDIT) ;
return TRUE ;
}
@ -836,7 +837,7 @@ static int adjustmode( int kind, int global) {
}
static int iovstring( int f, int n, const char *prompt, int (*fun)( char *)) {
static int iovstring( int f, int n, const char *prompt, boolean (*fun)( char *)) {
char *tstring ; /* string to add */
/* ask for string to insert */

View File

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

View File

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

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

18
tcap.c
View File

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

View File

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

View File

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

View File

@ -6,8 +6,6 @@
#define TYPEAH 1 /* type ahead causes update to be skipped */
#define HUGE 1000 /* Huge number (for row/col) */
extern int ttrow ; /* Row location of HW cursor */
extern int ttcol ; /* Column location of HW cursor */

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

2
utf8.h
View File

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

135
window.c
View File

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

View File

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

2
word.c
View File

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

View File

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

View File

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