1
0
mirror of https://github.com/rfivet/uemacs.git synced 2024-09-28 00:15:54 -04:00

Compare commits

..

No commits in common. "master" and "4.2.1" have entirely different histories.

95 changed files with 12705 additions and 8852 deletions

1
.gitattributes vendored
View File

@ -1 +0,0 @@
* text=auto

4
.gitignore vendored
View File

@ -1,4 +1,2 @@
ue em
*.o *.o
*.exe
*.dep

190
Makefile
View File

@ -1,5 +1,10 @@
# Makefile -- µEMACS # Makefile for emacs, updated Fri, Feb 13, 2015 12:02:52 PM
# Copyright © 2013-2022 Renaud Fivet
SRC=basic.c bind.c bindable.c buffer.c crypt.c display.c ebind.c eval.c exec.c execute.c file.c fileio.c flook.c input.c isearch.c line.c lock.c main.c mingw32.c mlout.c names.c pklock.c posix.c random.c region.c search.c spawn.c tcap.c termio.c utf8.c window.c word.c wrapper.c wscreen.c
OBJ=basic.o bind.o bindable.o buffer.o crypt.o display.o ebind.o eval.o exec.o execute.o file.o fileio.o flook.o input.o isearch.o line.o lock.o main.o mingw32.o mlout.o names.o pklock.o posix.o random.o region.o search.o spawn.o tcap.o termio.o utf8.o window.o word.o wrapper.o wscreen.o
HDR=basic.h bind.h bindable.h buffer.h crypt.h defines.h display.h ebind.h estruct.h eval.h exec.h execute.h file.h fileio.h flook.h input.h isearch.h line.h lock.h mlout.h names.h pklock.h random.h region.h retcode.h search.h spawn.h terminal.h termio.h utf8.h version.h window.h word.h wrapper.h wscreen.h
# DO NOT ADD OR MODIFY ANY LINES ABOVE THIS -- make source creates them
# Make the build silent by default # Make the build silent by default
V = V =
@ -13,27 +18,60 @@ else
endif endif
export E Q export E Q
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
# for windows based target, insure we strip the variant part
# CYGWIN_NT-6.1, CYGWIN_NT-6.1-WOW, CYGWIN_NT-6.1-WOW64, MINGW32_NT-6.1
uname_S := $(shell sh -c 'echo $(uname_S) | sed s/_.*$$//')
PROGRAM=ue PROGRAM=ue
CC=cc CC=gcc
WARNINGS=-pedantic -Wall -Wextra -Wstrict-prototypes -Wno-unused-parameter WARNINGS=-Wall -Wextra -Wstrict-prototypes -Wno-unused-parameter
CFLAGS=-O2 $(WARNINGS) CFLAGS=-O2 $(WARNINGS)
LDFLAGS=-s #CC=c89 +O3 # HP
LIBS=-lcurses #CFLAGS= -D_HPUX_SOURCE -DSYSV
DEFINES=-DPROGRAM=$(PROGRAM) -D_GNU_SOURCE # -DNDEBUG #CFLAGS=-O4 -DSVR4 # Sun
#CFLAGS=-O -qchars=signed # RS/6000
ifeq ($(uname_S),Linux)
DEFINES=-DAUTOCONF -DPROGRAM=$(PROGRAM) -DPOSIX -DUSG -D_BSD_SOURCE -D_SVID_SOURCE -D_XOPEN_SOURCE=600
LIBS=-lcurses
endif
ifeq ($(uname_S),FreeBSD)
DEFINES=-DAUTOCONF -DPOSIX -DSYSV -D_FREEBSD_C_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE -D_XOPEN_SOURCE=600
endif
ifeq ($(uname_S),Darwin)
DEFINES=-DAUTOCONF -DPOSIX -DSYSV -D_DARWIN_C_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE -D_XOPEN_SOURCE=600
endif
ifeq ($(uname_S),CYGWIN)
DEFINES=-DAUTOCONF -DCYGWIN -DPOSIX -DSYSV -DPROGRAM=$(PROGRAM)
LIBS=-lcurses
endif
ifeq ($(uname_S),MINGW32)
DEFINES=-DAUTOCONF -DSYSV -DMINGW32 -DPROGRAM=$(PROGRAM)
LIBS=
endif
#DEFINES=-DAUTOCONF
#LIBS=-ltermcap # BSD
#LIBS=-lcurses # SYSV
#LIBS=-ltermlib
#LIBS=-L/usr/lib/termcap -ltermcap
LFLAGS=-hbx
BINDIR=/usr/bin BINDIR=/usr/bin
LIBDIR=/usr/lib LIBDIR=/usr/lib
SRCS = $(sort $(wildcard *.c)) $(PROGRAM): $(OBJ)
$(E) " LINK " $@
$(Q) $(CC) $(LDFLAGS) $(DEFINES) -o $@ $(OBJ) $(LIBS)
$(PROGRAM): $(SRCS:.c=.o) SPARSE=sparse
$(E) " LINK " $@ SPARSE_FLAGS=-D__LITTLE_ENDIAN__ -D__x86_64__ -D__linux__ -D__unix__
$(Q) $(CC) $(LDFLAGS) -o $@ $+ $(LIBS)
sparse:
$(SPARSE) $(SPARSE_FLAGS) $(DEFINES) $(SRC)
clean: clean:
$(E) " CLEAN" $(E) " CLEAN"
$(Q) rm -f $(PROGRAM) *.dep *.o $(Q) rm -f $(PROGRAM) core lintout makeout tags Makefile.bak *.o
install: $(PROGRAM) install: $(PROGRAM)
strip $(PROGRAM) strip $(PROGRAM)
@ -43,16 +81,124 @@ install: $(PROGRAM)
chmod 755 ${BINDIR}/$(PROGRAM) chmod 755 ${BINDIR}/$(PROGRAM)
chmod 644 ${LIBDIR}/emacs.hlp ${LIBDIR}/.emacsrc chmod 644 ${LIBDIR}/emacs.hlp ${LIBDIR}/.emacsrc
lint: ${SRC}
@rm -f lintout
lint ${LFLAGS} ${SRC} >lintout
cat lintout
splint:
splint -weak $(DEFINES) $(SRC) -booltype boolean -booltrue TRUE -boolfalse FALSE +posixlib +matchanyintegral
errs:
@rm -f makeout
make $(PROGRAM) >makeout
tags: ${SRC}
@rm -f tags
ctags ${SRC}
source:
@mv Makefile Makefile.bak
@echo "# Makefile for emacs, updated `date`" >Makefile
@echo '' >>Makefile
#Sorted
@echo SRC=`ls *.c` >>Makefile
@echo OBJ=`ls *.c | sed s/c$$/o/` >>Makefile
@echo HDR=`ls *.h` >>Makefile
#UnSorted
# @echo SRC=$(wildcard *.c) >>Makefile
# @echo OBJ=$(patsubst %.c,%.o,$(wildcard *.c)) >>Makefile
# @echo HDR=$(wildcard *.h) >>Makefile
@echo '' >>Makefile
@sed -n -e '/^# DO NOT ADD OR MODIFY/,$$p' <Makefile.bak >>Makefile
depend: ${SRC}
@mv Makefile Makefile.bak
@sed -n -e '1,/^# DO NOT DELETE THIS LINE/p' Makefile.bak > Makefile
@echo >> Makefile
@for i in ${SRC}; do\
cc ${DEFINES} -MM $$i ; done >> Makefile
@echo '' >>Makefile
@echo '# DEPENDENCIES MUST END AT END OF FILE' >>Makefile
@echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >>Makefile
@echo '# see make depend above' >>Makefile
.c.o: .c.o:
$(E) " CC " $@ $(E) " CC " $@
$(Q) $(CC) $(CFLAGS) $(DEFINES) -c $*.c $(Q) ${CC} ${CFLAGS} ${DEFINES} -c $*.c
%.dep: %.c # DO NOT DELETE THIS LINE -- make depend uses it
$(E) " DEPEND" $@
$(Q) $(CC) $(DEFINES) -MM $< > $@
ifneq ($(MAKECMDGOALS),clean) basic.o: basic.c basic.h buffer.h crypt.h line.h retcode.h utf8.h \
include $(SRCS:.c=.dep) estruct.h input.h bind.h mlout.h random.h terminal.h defines.h window.h
endif bind.o: bind.c bind.h estruct.h bindable.h buffer.h crypt.h line.h \
retcode.h utf8.h display.h ebind.h exec.h file.h flook.h input.h names.h \
window.h defines.h
bindable.o: bindable.c bindable.h defines.h buffer.h crypt.h line.h \
retcode.h utf8.h display.h estruct.h file.h input.h bind.h lock.h \
mlout.h terminal.h
buffer.o: buffer.c buffer.h crypt.h line.h retcode.h utf8.h defines.h \
estruct.h file.h input.h bind.h mlout.h window.h
crypt.o: crypt.c crypt.h
display.o: display.c display.h estruct.h buffer.h crypt.h line.h \
retcode.h utf8.h input.h bind.h termio.h terminal.h defines.h version.h \
wrapper.h window.h
ebind.o: ebind.c ebind.h basic.h bind.h estruct.h bindable.h buffer.h \
crypt.h line.h retcode.h utf8.h eval.h exec.h file.h isearch.h random.h \
region.h search.h spawn.h window.h defines.h word.h
eval.o: eval.c eval.h basic.h bind.h buffer.h crypt.h line.h retcode.h \
utf8.h display.h estruct.h exec.h execute.h flook.h input.h random.h \
search.h terminal.h defines.h termio.h version.h window.h
exec.o: exec.c exec.h retcode.h buffer.h crypt.h line.h utf8.h bind.h \
display.h estruct.h eval.h file.h flook.h input.h random.h window.h \
defines.h
execute.o: execute.c execute.h estruct.h bind.h random.h display.h file.h \
buffer.h crypt.h line.h retcode.h utf8.h mlout.h window.h defines.h
file.o: file.c file.h buffer.h crypt.h line.h retcode.h utf8.h defines.h \
estruct.h execute.h fileio.h input.h bind.h lock.h mlout.h window.h
fileio.o: fileio.c fileio.h crypt.h retcode.h defines.h utf8.h
flook.o: flook.c flook.h retcode.h defines.h fileio.h crypt.h
input.o: input.c input.h bind.h estruct.h bindable.h display.h exec.h \
retcode.h names.h terminal.h defines.h utf8.h wrapper.h
isearch.o: isearch.c isearch.h basic.h buffer.h crypt.h line.h retcode.h \
utf8.h display.h estruct.h exec.h input.h bind.h search.h terminal.h \
defines.h window.h
line.o: line.c line.h retcode.h utf8.h buffer.h crypt.h estruct.h mlout.h \
window.h defines.h
lock.o: lock.c estruct.h lock.h
main.o: main.c estruct.h basic.h bind.h bindable.h buffer.h crypt.h \
line.h retcode.h utf8.h display.h eval.h execute.h file.h input.h lock.h \
mlout.h random.h search.h terminal.h defines.h termio.h version.h \
window.h
mingw32.o: mingw32.c
mlout.o: mlout.c mlout.h
names.o: names.c names.h basic.h bind.h bindable.h buffer.h crypt.h \
line.h retcode.h utf8.h display.h estruct.h eval.h exec.h file.h \
isearch.h region.h random.h search.h spawn.h window.h defines.h word.h
pklock.o: pklock.c estruct.h pklock.h
posix.o: posix.c termio.h estruct.h retcode.h utf8.h
random.o: random.c random.h basic.h buffer.h crypt.h line.h retcode.h \
utf8.h display.h estruct.h execute.h input.h bind.h search.h terminal.h \
defines.h window.h
region.o: region.c region.h line.h retcode.h utf8.h buffer.h crypt.h \
estruct.h mlout.h random.h window.h defines.h
search.o: search.c search.h line.h retcode.h utf8.h basic.h buffer.h \
crypt.h display.h estruct.h input.h bind.h mlout.h terminal.h defines.h \
window.h
spawn.o: spawn.c spawn.h defines.h buffer.h crypt.h line.h retcode.h \
utf8.h display.h estruct.h exec.h file.h flook.h input.h bind.h \
terminal.h window.h
tcap.o: tcap.c terminal.h defines.h retcode.h display.h estruct.h \
termio.h
termio.o: termio.c
utf8.o: utf8.c utf8.h
window.o: window.c window.h defines.h buffer.h crypt.h line.h retcode.h \
utf8.h basic.h display.h estruct.h execute.h terminal.h wrapper.h
word.o: word.c word.h basic.h buffer.h crypt.h line.h retcode.h utf8.h \
estruct.h mlout.h random.h region.h window.h defines.h
wrapper.o: wrapper.c wrapper.h
wscreen.o: wscreen.c wscreen.h
# end of Makefile # DEPENDENCIES MUST END AT END OF FILE
# IF YOU PUT STUFF HERE IT WILL GO AWAY
# see make depend above

View File

@ -1,31 +1,19 @@
# README # # README #
µEMACS (ue) on Cygwin/MSYS2/Linux/NetBSD/OpenBSD, based on uEmacs/PK (em) Ciguë is µEMACS (ue) on Cygwin/Linux, based on uEmacs/PK (em) from kernel.org.
from [kernel.org](https://git.kernel.org/pub/scm/editors/uemacs/uemacs.git/).
### Changes compare to uEmacs/PK ### ### Changes compare to uEmacs/PK ###
* Line termination detection with new buffer mode (either Unix or DOS). * Line termination detection with new buffer mode (either Unix or DOS).
* Encoding detection (ASCII, Extended ASCII, UTF-8 or Mixed). * Encoding detection (ASCII, Extended ASCII, UTF-8 or Mixed).
* Some fixes related to size either unchecked or limited (strcpy, insert-string, filenames, $kill).
* Some fixes related to size either unchecked or limited (strcpy, * Major refactoring of headers and file dependencies, hopefully to improve maintenance.
insert-string, filenames, $kill). * Reactivation of target 'source' and 'depend' in Makefile.
* Some defaults changed due to 'finger habits': ue instead of em, ^S in commands mapping...
* Major refactoring of headers and file dependencies, hopefully to
improve maintenance.
* 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 ### ### How to build ###
* dependencies: ncurses.
* make depend ; make
* MINGW32 target is experimental and lacks screen/kbd support.
* dependencies: (gcc || clang) && gmake && ncurses-devel. ### Badges ###
[![Coverity Status](https://scan.coverity.com/projects/4449/badge.svg)](https://scan.coverity.com/projects/4449)
* make

529
basic.c
View File

@ -1,318 +1,345 @@
/* basic.c -- implements basic.h */ /* basic.c -- implements basic.h */
#include "basic.h" #include "basic.h"
/* The routines in this file move the cursor around on the screen. They #define CVMVAS 1 /* arguments to page forward/back in pages */
compute a new value for the cursor, then adjust ".". The display code
always updates the cursor location, so only moves between lines, or
functions that adjust the top line in the window and invalidate the
framing, are hard.
modified by Petri Kutvonen /* basic.c
*
* The routines in this file move the cursor around on the screen. They
* compute a new value for the cursor, then adjust ".". The display code
* always updates the cursor location, so only moves between lines, or
* functions that adjust the top line in the window and invalidate the
* framing, are hard.
*
* modified by Petri Kutvonen
*/ */
#include <assert.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "buffer.h"
#include "estruct.h"
#include "input.h" #include "input.h"
#include "line.h"
#include "mlout.h" #include "mlout.h"
#include "random.h" #include "random.h"
#include "terminal.h" #include "terminal.h"
#include "utf8.h"
#include "window.h" #include "window.h"
#define CVMVAS 1 /* arguments to page forward/back in pages */
int overlap = 0 ; /* $overlap: line overlap in forw/back page */ int overlap = 0 ; /* line overlap in forw/back page */
int curgoal ; /* $target: column goal for C-P, C-N */ int curgoal ; /* Goal for C-P, C-N */
/* This routine, given a pointer to a struct line, and the current cursor /*
goal column, return the best choice for the offset. The offset is * This routine, given a pointer to a struct line, and the current cursor goal
returned. Used by "C-N" and "C-P". * column, return the best choice for the offset. The offset is returned.
* Used by "C-N" and "C-P".
*/ */
static unsigned getgoal( line_p dlp) { static unsigned getgoal( struct line *dlp) {
int col = 0 ; int col ;
const unsigned len = llength( dlp) ; unsigned idx ;
unsigned idx = 0 ; const unsigned len = llength( dlp) ;
while( idx < len) {
unicode_t c ;
unsigned width = utf8_to_unicode( dlp->l_text, idx, len, &c) ;
/* Take tabs, ^X and \xx hex characters into account */ col = 0 ;
if( c == '\t') idx = 0 ;
col += tabwidth - col % tabwidth ; while( idx < len) {
else if( c < 0x20 || c == 0x7F) /* ^x */ unicode_t c ;
col += 2 ; unsigned width = utf8_to_unicode( dlp->l_text, idx, len, &c) ;
else if( c >= 0x80 && c < 0xA0) /* \xx */
col += 3 ;
else
col += utf8_width( c) ;
if( col > curgoal) /* Take tabs, ^X and \xx hex characters into account */
break ; if( c == '\t')
else col |= tabmask ;
idx += width ; else if( c < 0x20 || c == 0x7F)
} col += 1 ;
else if( c >= 0x80 && c <= 0xA0)
col += 2 ;
return idx ; col += 1 ;
if( col > curgoal)
break ;
idx += width ;
}
return idx ;
} }
/*
/* Move the cursor to the beginning of the current line of active window. */ * Move the cursor to the beginning of the current line.
TBINDABLE( gotobol) {
curwp->w_doto = 0 ;
return TRUE ;
}
/* Move the cursor to the end of the current line of active window. */
TBINDABLE( gotoeol) {
curwp->w_doto = llength( curwp->w_dotp) ;
return TRUE ;
}
/* Goto the beginning of the buffer. Massive adjustment of dot. This is
considered to be hard motion; it really isn't if the original value of
dot is the same as the new value of dot. Normally bound to "M-<".
*/ */
TBINDABLE( gotobob) { int gotobol(int f, int n)
curwp->w_dotp = lforw( curbp->b_linep) ; {
curwp->w_doto = 0 ; curwp->w_doto = 0;
curwp->w_flag |= WFHARD ; return TRUE;
return TRUE ;
} }
/*
/* Move to the end of the buffer. Dot is always put at the end of the file * Move the cursor to the end of the current line. Trivial. No errors.
(ZJ). The standard screen code does most of the hard parts of update.
Bound to "M->".
*/ */
TBINDABLE( gotoeob) { int gotoeol(int f, int n)
curwp->w_dotp = curbp->b_linep ; {
curwp->w_doto = 0 ; curwp->w_doto = llength(curwp->w_dotp);
curwp->w_flag |= WFHARD ; return TRUE;
return TRUE ;
} }
/*
/* Move forward by full lines. If the number of lines to move is less than * Move to a particular line.
zero, call the backward line function to actually do it. The last
command controls how the goal column is set. Bound to "C-N". No errors
are possible.
*/
BBINDABLE( forwline) {
assert( f == TRUE || n == 1) ;
/* if the last command was not a line move, reset the goal column */
if( (lastflag & CFCPCN) == 0)
curgoal = getccol( FALSE) ;
/* flag this command as a line move */
thisflag |= CFCPCN ;
/* and move the point down */
if( n) {
line_p dlp = curwp->w_dotp ;
if( n > 0)
while( n && dlp != curbp->b_linep) {
dlp = lforw( dlp) ;
n -= 1 ;
}
else {
while( n && lback( dlp) != curbp->b_linep) {
dlp = lback( dlp) ;
n += 1 ;
}
}
/* resetting the current position */
curwp->w_dotp = dlp ;
curwp->w_doto = getgoal( dlp) ;
curwp->w_flag |= WFMOVE ;
}
return (n == 0) ? TRUE : FALSE ;
}
/* This function is like "forwline", but goes backwards. The scheme is
exactly the same. Check for arguments that are less than zero and call
your alternate. Figure out the new line and call "movedot" to perform
the motion. No errors are possible. Bound to "C-P".
*/
BBINDABLE( backline) {
assert( f == TRUE || n == 1) ;
return forwline( TRUE, -n) ;
}
/* Move to a particular line.
* *
* @n: The specified line position at the current buffer. * @n: The specified line position at the current buffer.
*/ */
BINDABLE( gotoline) { int gotoline( int f, int n) {
/* Get an argument if one doesn't exist. */ /* Get an argument if one doesnt exist. */
if( f == FALSE) { if( f == FALSE) {
char *arg ; /* Buffer to hold argument. */ int status ;
char *arg ; /* Buffer to hold argument. */
int status = newmlarg( &arg, "goto-line: ", 0) ; status = newmlarg( &arg, "Line to GOTO: ", 0) ;
if( status != TRUE) if( status != TRUE) {
return status ; mloutstr( "(Aborted)") ;
return status ;
}
n = atoi( arg) ; n = atoi( arg) ;
free( arg) ; free( arg) ;
f = TRUE ; }
}
/* Handle the case where the user may be passed something like this: /* Handle the case where the user may be passed something like this:
* ue filename + * em filename +
* In this case we just go to the end of the buffer. * In this case we just go to the end of the buffer.
*/ */
if( n == 0) if (n == 0)
return gotoeob( f, n) ; return gotoeob(f, n);
/* If a bogus argument was passed, then returns false. */ /* If a bogus argument was passed, then returns false. */
if( n < 0) if (n < 0)
return FALSE ; return FALSE;
/* First, we go to the begin of the buffer. */ /* First, we go to the begin of the buffer. */
gotobob( f, n) ; gotobob(f, n);
return (n == 1) ? TRUE : forwline( TRUE, n - 1) ; return forwline(f, n - 1);
} }
/*
/* Scroll forward by a specified number of lines, or by a full page if no * Goto the beginning of the buffer. Massive adjustment of dot. This is
argument. Bound to "C-V". The "2" in the arithmetic on the window size * considered to be hard motion; it really isn't if the original value of dot
is the overlap; this value is the default overlap value in ITS EMACS. * is the same as the new value of dot. Normally bound to "M-<".
Because this zaps the top line in the display window, we have to do a
hard update.
*/ */
TBINDABLE( forwpage) { int gotobob(int f, int n)
line_p lp ; {
curwp->w_dotp = lforw(curbp->b_linep);
curwp->w_doto = 0;
curwp->w_flag |= WFHARD;
return TRUE;
}
if( f == FALSE) { /*
* Move to the end of the buffer. Dot is always put at the end of the file
* (ZJ). The standard screen code does most of the hard parts of update.
* Bound to "M->".
*/
int gotoeob(int f, int n)
{
curwp->w_dotp = curbp->b_linep;
curwp->w_doto = 0;
curwp->w_flag |= WFHARD;
return TRUE;
}
/*
* Move forward by full lines. If the number of lines to move is less than
* zero, call the backward line function to actually do it. The last command
* controls how the goal column is set. Bound to "C-N". No errors are
* possible.
*/
int forwline(int f, int n)
{
struct line *dlp;
if (n < 0)
return backline(f, -n);
/* if we are on the last line as we start....fail the command */
if (curwp->w_dotp == curbp->b_linep)
return FALSE;
/* if the last command was not note a line move,
reset the goal column */
if ((lastflag & CFCPCN) == 0)
curgoal = getccol(FALSE);
/* flag this command as a line move */
thisflag |= CFCPCN;
/* and move the point down */
dlp = curwp->w_dotp;
while (n-- && dlp != curbp->b_linep)
dlp = lforw(dlp);
/* reseting the current position */
curwp->w_dotp = dlp;
curwp->w_doto = getgoal(dlp);
curwp->w_flag |= WFMOVE;
return TRUE;
}
/*
* This function is like "forwline", but goes backwards. The scheme is exactly
* the same. Check for arguments that are less than zero and call your
* alternate. Figure out the new line and call "movedot" to perform the
* motion. No errors are possible. Bound to "C-P".
*/
int backline(int f, int n)
{
struct line *dlp;
if (n < 0)
return forwline(f, -n);
/* if we are on the last line as we start....fail the command */
if (lback(curwp->w_dotp) == curbp->b_linep)
return FALSE;
/* if the last command was not note a line move,
reset the goal column */
if ((lastflag & CFCPCN) == 0)
curgoal = getccol(FALSE);
/* flag this command as a line move */
thisflag |= CFCPCN;
/* and move the point up */
dlp = curwp->w_dotp;
while (n-- && lback(dlp) != curbp->b_linep)
dlp = lback(dlp);
/* reseting the current position */
curwp->w_dotp = dlp;
curwp->w_doto = getgoal(dlp);
curwp->w_flag |= WFMOVE;
return TRUE;
}
/*
* Scroll forward by a specified number of lines, or by a full page if no
* argument. Bound to "C-V". The "2" in the arithmetic on the window size is
* the overlap; this value is the default overlap value in ITS EMACS. Because
* this zaps the top line in the display window, we have to do a hard update.
*/
int forwpage(int f, int n)
{
struct line *lp;
if (f == FALSE) {
#if SCROLLCODE #if SCROLLCODE
if (term.t_scroll != NULL) /* $scroll == FALSE */ if (term.t_scroll != NULL)
if (overlap == 0) /* $overlap == 0 */ if (overlap == 0)
n = curwp->w_ntrows * 2 / 3 ; n = curwp->w_ntrows / 3 * 2;
else else
n = curwp->w_ntrows - overlap; n = curwp->w_ntrows - overlap;
else else
#endif #endif
n = curwp->w_ntrows - 2; /* Default scroll. */ n = curwp->w_ntrows - 2; /* Default scroll. */
if (n <= 0) /* Forget the overlap. */
if (n <= 0) /* Forget the overlap. */ n = 1; /* If tiny window. */
n = 1; /* If tiny window. */ } else if (n < 0)
} else if( n < 0) return backpage(f, -n);
return backpage( f, -n) ;
#if CVMVAS #if CVMVAS
else /* Convert from pages. */ else /* Convert from pages. */
n *= curwp->w_ntrows; /* To lines. */ n *= curwp->w_ntrows; /* To lines. */
#endif #endif
lp = curwp->w_linep;
lp = curwp->w_dotp ; while (n-- && lp != curbp->b_linep)
while( n && lp != curbp->b_linep) { lp = lforw(lp);
lp = lforw( lp) ; curwp->w_linep = lp;
n -= 1 ; curwp->w_dotp = lp;
} curwp->w_doto = 0;
curwp->w_dotp = lp ;
curwp->w_doto = 0 ;
reposition( TRUE, 0) ; /* center at dot, always succeed */
#if SCROLLCODE #if SCROLLCODE
curwp->w_flag |= WFHARD | WFKILLS; curwp->w_flag |= WFHARD | WFKILLS;
#else #else
curwp->w_flag |= WFHARD; curwp->w_flag |= WFHARD;
#endif #endif
return TRUE ; return TRUE;
} }
/*
/* This command is like "forwpage", but it goes backwards. The "2", like * This command is like "forwpage", but it goes backwards. The "2", like
above, is the overlap between the two windows. The value is from the * above, is the overlap between the two windows. The value is from the ITS
ITS EMACS manual. Bound to "M-V". We do a hard update for exactly the * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
same reason. * reason.
*/ */
TBINDABLE( backpage) { int backpage(int f, int n)
line_p lp ; {
struct line *lp;
if( f == FALSE) { /* interactive, default n = 1 supplied */
/* in interactive mode, first move dot to top of window */
if( curwp->w_dotp != curwp->w_linep) {
curwp->w_dotp = curwp->w_linep ;
curwp->w_doto = 0 ;
/* curwp->w_flag |= WFMOVE ; */
return TRUE ;
}
if (f == FALSE) {
#if SCROLLCODE #if SCROLLCODE
if (term.t_scroll != NULL) /* $scroll != FALSE */ if (term.t_scroll != NULL)
if (overlap == 0) /* $overlap == 0 */ if (overlap == 0)
n = curwp->w_ntrows * 2 / 3 ; n = curwp->w_ntrows / 3 * 2;
else else
n = curwp->w_ntrows - overlap; n = curwp->w_ntrows - overlap;
else else
#endif #endif
n = curwp->w_ntrows - 2; /* Default scroll. */ n = curwp->w_ntrows - 2; /* Default scroll. */
if (n <= 0) /* Don't blow up if the. */
if (n <= 0) /* Don't blow up if the. */ n = 1; /* Window is tiny. */
n = 1; /* Window is tiny. */ } else if (n < 0)
} else if (n < 0) return forwpage(f, -n);
return forwpage(f, -n);
#if CVMVAS #if CVMVAS
else /* Convert from pages. */ else /* Convert from pages. */
n *= curwp->w_ntrows; /* To lines. */ n *= curwp->w_ntrows; /* To lines. */
#endif #endif
lp = curwp->w_linep;
/* lp = curwp->w_linep; */ while (n-- && lback(lp) != curbp->b_linep)
lp = curwp->w_dotp ; lp = lback(lp);
while( n && lback( lp) != curbp->b_linep) { curwp->w_linep = lp;
lp = lback( lp) ; curwp->w_dotp = lp;
n -= 1 ; curwp->w_doto = 0;
}
/* curwp->w_linep = lp; */
curwp->w_dotp = lp;
curwp->w_doto = 0;
reposition( TRUE, (f == FALSE) ? 1 : 0) ;
#if SCROLLCODE #if SCROLLCODE
curwp->w_flag |= WFHARD | WFINS; curwp->w_flag |= WFHARD | WFINS;
#else #else
curwp->w_flag |= WFHARD; curwp->w_flag |= WFHARD;
#endif #endif
return TRUE; return TRUE;
} }
/*
/* Set the mark in the current window to the value of "." in the window. * Set the mark in the current window to the value of "." in the window. No
No errors are possible. Bound to M-. set-mark. * errors are possible. Bound to "M-.".
*/ */
TBINDABLE( setmark) { int setmark(int f, int n)
curwp->w_markp = curwp->w_dotp ; {
curwp->w_marko = curwp->w_doto ; curwp->w_markp = curwp->w_dotp;
mloutstr( "(Mark set)") ; curwp->w_marko = curwp->w_doto;
return TRUE ; mloutstr( "(Mark set)") ;
return TRUE ;
} }
/*
/* Swap the values of "." and "mark" in the current window. If no mark as * Swap the values of "." and "mark" in the current window. This is pretty
been previously set, set it. Bound to C-X C-X exchange-point-and-mark. * easy, bacause all of the hard work gets done by the standard routine
* that moves the mark about. The only possible error is "no mark". Bound to
* "C-X C-X".
*/ */
TBINDABLE( swapmark) { int swapmark(int f, int n)
line_p odotp = curwp->w_dotp ; {
int odoto = curwp->w_doto ; struct line *odotp;
if( curwp->w_markp) { int odoto;
curwp->w_dotp = curwp->w_markp ;
curwp->w_doto = curwp->w_marko ;
curwp->w_flag |= WFMOVE ;
}
curwp->w_markp = odotp ; if( curwp->w_markp == NULL) {
curwp->w_marko = odoto ; mloutstr( "No mark in this window") ;
return TRUE ; return FALSE ;
}
odotp = curwp->w_dotp;
odoto = curwp->w_doto;
curwp->w_dotp = curwp->w_markp;
curwp->w_doto = curwp->w_marko;
curwp->w_markp = odotp;
curwp->w_marko = odoto;
curwp->w_flag |= WFMOVE;
return TRUE;
} }
/* end of basic.c */

38
basic.h
View File

@ -1,32 +1,20 @@
/* basic.h -- basic commands for cursor movement in active window */
#ifndef _BASIC_H_ #ifndef _BASIC_H_
#define _BASIC_H_ #define _BASIC_H_
#include "names.h" /* BINDABLE() */ extern int overlap ; /* line overlap in forw/back page */
extern int curgoal ; /* Goal for C-P, C-N */
/* $overlap is the size of the line overlap when kbd calls page forw/back
if 0, page will move by 2/3 of the window size (1/3 page overlap)
default to 0
*/
extern int overlap ; /* $overlap: line overlap in forw/back page */
/* $target (== curgoal) is the column target when doing line move */ int gotobol( int f, int n) ;
extern int curgoal ; /* $target: Goal for C-P previous-line, C-N next-line */ int gotoeol( int f, int n) ;
int gotoline( int f, int n) ;
int gotobob( int f, int n) ;
/* Bindable functions */ int gotoeob( int f, int n) ;
BBINDABLE( backline) ; int forwline( int f, int n) ;
TBINDABLE( backpage) ; int backline( int f, int n) ;
BBINDABLE( forwline) ; int forwpage( int f, int n) ;
TBINDABLE( forwpage) ; int backpage( int f, int n) ;
TBINDABLE( gotobob) ; int setmark( int f, int n) ;
TBINDABLE( gotobol) ; int swapmark( int f, int n) ;
TBINDABLE( gotoeob) ;
TBINDABLE( gotoeol) ;
BINDABLE( gotoline) ;
TBINDABLE( setmark) ;
TBINDABLE( swapmark) ;
#endif #endif
/* end of basic.h */

834
bind.c
View File

@ -1,215 +1,418 @@
/* bind.c -- implements bind.h */ /* bind.c -- implements bind.h */
#include "bind.h" #include "bind.h"
/* This file is for functions having to do with key bindings, /* bind.c
*
* This file is for functions having to do with key bindings,
* descriptions, help commands and startup file. * descriptions, help commands and startup file.
* *
* Written 11-feb-86 by Daniel Lawrence * Written 11-feb-86 by Daniel Lawrence
* Modified by Petri Kutvonen * Modified by Petri Kutvonen
*/ */
#include <assert.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "estruct.h"
#include "bindable.h" #include "bindable.h"
#include "buffer.h" #include "buffer.h"
#include "display.h" /* upmode(), ostring() */ #include "display.h"
#include "ebind.h"
#include "exec.h" #include "exec.h"
#include "file.h" #include "file.h"
#include "flook.h" #include "flook.h"
#include "input.h" #include "input.h"
#include "line.h" #include "line.h"
#include "mlout.h"
#include "names.h" #include "names.h"
#include "util.h"
#include "window.h" #include "window.h"
#if APROP
static int buildlist( char *mstring) ; static int buildlist( char *mstring) ;
static char *cmdstr( unsigned c, char *seq) ; static int strinc( char *source, char *sub) ;
#endif
static void cmdstr( int c, char *seq) ;
static unsigned int getckey( int mflag) ; static unsigned int getckey( int mflag) ;
static unsigned int stock( char *keyname) ; static unsigned int stock( char *keyname) ;
static const char *getfname( unsigned keycode, const char *failmsg) ; static int unbindchar( unsigned c) ;
static char *getfname( fn_t) ;
/* give me some help!!!! bring up a fake buffer and read the help file into int help(int f, int n)
it with view mode { /* give me some help!!!!
*/ bring up a fake buffer and read the help file
BINDABLE( help) { into it with view mode */
struct window *wp; /* scaning pointer to windows */
struct buffer *bp; /* buffer pointer to help */
char *fname = NULL; /* ptr to file returned by flook() */ char *fname = NULL; /* ptr to file returned by flook() */
/* first check if we are already here */ /* first check if we are already here */
buffer_p bp = bfind( hlpfname, FALSE, BFINVS); bp = bfind( hlpfname, FALSE, BFINVS);
if( bp == curbp)
return TRUE ;
if( bp == NULL) { if (bp == NULL) {
fname = flook( hlpfname, FALSE) ; fname = flook( hlpfname, FALSE);
if( fname == NULL) if (fname == NULL) {
return mloutfail( "(Help file is not online)") ; mlwrite("(Help file is not online)");
return FALSE;
}
} }
/* split the current window to make room for the help stuff */ /* split the current window to make room for the help stuff */
if( wheadp->w_wndp == NULL /* One window */ if (splitwind(FALSE, 1) == FALSE)
&& splitwind( FALSE, 1) == FALSE) /* Split it */ return FALSE;
return FALSE ;
if( bp == NULL) { if (bp == NULL) {
/* and read the stuff in */ /* and read the stuff in */
if( getfile( fname, FALSE) == FALSE) if (getfile(fname, FALSE) == FALSE)
return FALSE ; return FALSE;
} else } else
swbuffer( bp) ; swbuffer(bp);
/* make this window in VIEW mode, update all mode lines */ /* make this window in VIEW mode, update all mode lines */
curwp->w_bufp->b_mode |= MDVIEW; curwp->w_bufp->b_mode |= MDVIEW;
curwp->w_bufp->b_flag |= BFINVS; curwp->w_bufp->b_flag |= BFINVS;
upmode() ; wp = wheadp;
return TRUE ; while (wp != NULL) {
wp->w_flag |= WFMODE;
wp = wp->w_wndp;
}
return TRUE;
} }
int deskey(int f, int n)
{ /* describe the command for a certain key */
int c; /* key to describe */
char *ptr; /* string pointer to scan output strings */
char outseq[NSTRING]; /* output buffer for command sequence */
static boolean invalidkey( void) { /* prompt the user to type us a key to describe */
return mloutfail( "(Invalid key sequence)") ; mlwrite(": describe-key ");
/* get the command sequence to describe
change it to something we can print as well */
c = getckey( FALSE) ;
mlwrite( ": describe-key 0x%x, ", c) ;
cmdstr( c, &outseq[ 0]) ;
/* and dump it out */
ostring(outseq);
ostring(" ");
/* find the right ->function */
if ((ptr = getfname(getbind(c))) == NULL)
ptr = "Not Bound";
/* output the command sequence */
ostring(ptr);
return TRUE;
} }
/*
/* describe the command for a certain key */ * bindtokey:
BINDABLE( deskey) {
const char cmdname[] = "describe-key" ;
char outseq[ 8] ; /* output buffer for keystroke sequence */
/* prompt the user to type a key to describe */
mloutfmt( "%s: ", cmdname) ;
/* get the command sequence to describe
* change it to something we can print as well */
unsigned keycode = getckey( FALSE) ;
if( keycode == (unsigned) ~0)
return invalidkey() ;
/* output the command sequence */
mloutfmt( "%s %s: 0x%x, %s", cmdname, cmdstr( keycode, outseq), keycode,
getfname( keycode, "Not Bound")) ;
return TRUE ;
}
/* bindtokey:
* add a new key to the key binding table * add a new key to the key binding table
* *
* int f, n; command arguments [IGNORED] * int f, n; command arguments [IGNORED]
*/ */
BINDABLE( bindtokey) { int bindtokey(int f, int n)
kbind_p ktp ; /* pointer into the command table */ {
char outseq[ 8] ; /* output buffer for keystroke sequence */ unsigned int c; /* command key to bind */
fn_t kfunc; /* ptr to the requested function to bind to */
struct key_tab *ktp; /* pointer into the command table */
int found; /* matched command flag */
char outseq[80]; /* output buffer for keystroke sequence */
/* prompt the user to type in a key to bind */ /* prompt the user to type in a key to bind */
mloutstr( "bind-to-key: ") ; mlwrite(": bind-to-key ");
/* get the function name to bind it to */ /* get the function name to bind it to */
nbind_p nbp = getname() ; kfunc = getname();
if( nbp == NULL) /* abort */ if (kfunc == NULL) {
return FALSE ; mlwrite("(No such function)");
return FALSE;
}
ostring(" ");
fnp_t kfunc = nbp->n_func ; /* get the command sequence to bind */
if( kfunc == NULL) c = getckey((kfunc == metafn) || (kfunc == cex) ||
return mloutfail( "(No such function)") ; (kfunc == unarg) || (kfunc == ctrlg));
mloutfmt( "bind-to-key %s: ", bind_name( nbp)) ; /* change it to something we can print as well */
cmdstr(c, &outseq[0]);
/* get the command sequence to bind */ /* and dump it out */
boolean prefix_f = (kfunc == (fnp_t) metafn) || (kfunc == (fnp_t) cex) || ostring(outseq);
(kfunc == (fnp_t) unarg) || (kfunc == (fnp_t) ctrlg) ;
int c = getckey( prefix_f) ;
if( c == ~0)
return invalidkey() ;
/* change it to something we can print as well */ /* if the function is a prefix key */
/* and dump it out */ if (kfunc == metafn || kfunc == cex ||
ostring( cmdstr( c, outseq)) ; kfunc == unarg || kfunc == ctrlg) {
/* key sequence can't be an active prefix key */ /* search for an existing binding for the prefix key */
if( c == metac || c == ctlxc || c == reptc || c == abortc) { ktp = &keytab[0];
if( (c == metac && kfunc == (fnp_t) metafn) found = FALSE;
|| (c == ctlxc && kfunc == (fnp_t) cex) while (ktp->k_fp != NULL) {
|| (c == reptc && kfunc == (fnp_t) unarg) if (ktp->k_fp == kfunc)
|| (c == abortc && kfunc == (fnp_t) ctrlg)) unbindchar(ktp->k_code);
return TRUE ; /* be silent if keep current */ ++ktp;
}
return mloutfail( "(Can't bind to active prefix)") ; /* reset the appropriate global prefix variable */
if (kfunc == metafn)
metac = c;
if (kfunc == cex)
ctlxc = c;
if (kfunc == unarg)
reptc = c;
if (kfunc == ctrlg)
abortc = c;
} }
/* if the function is a prefix key */ /* search the table to see if it exists */
if( prefix_f) { ktp = &keytab[0];
/* remove existing binding for the prefix */ found = FALSE;
for( ktp = keytab ; ktp->k_code != 0 ; ktp++) while (ktp->k_fp != NULL) {
if( ktp->k_nbp == nbp) { if (ktp->k_code == c) {
delkeybinding( ktp->k_code) ; found = TRUE;
break ; break;
} }
++ktp;
/* set the appropriate global prefix variable */
if( kfunc == (fnp_t) metafn)
metac = c ;
else if( kfunc == (fnp_t) cex)
ctlxc = c ;
if( kfunc == (fnp_t) unarg)
reptc = c ;
if( kfunc == (fnp_t) ctrlg)
abortc = c ;
} }
ktp = setkeybinding( c, nbp) ; if (found) { /* it exists, just change it then */
if( ktp->k_code == 0) ktp->k_fp = kfunc;
return mloutfail( "Binding table FULL!") ; } else { /* otherwise we need to add it to the end */
/* if we run out of binding room, bitch */
if (ktp >= &keytab[NBINDS]) {
mlwrite("Binding table FULL!");
return FALSE;
}
return TRUE ; ktp->k_code = c; /* add keycode */
ktp->k_fp = kfunc; /* and the function pointer */
++ktp; /* and make sure the next is null */
ktp->k_code = 0;
ktp->k_fp = NULL;
}
return TRUE;
} }
/*
/* unbindkey: * unbindkey:
* delete a key from the key binding table * delete a key from the key binding table
* *
* int f, n; command arguments [IGNORED] * int f, n; command arguments [IGNORED]
*/ */
BINDABLE( unbindkey) { int unbindkey(int f, int n)
char outseq[ 8] ; /* output buffer for keystroke sequence */ {
int c; /* command key to unbind */
char outseq[80]; /* output buffer for keystroke sequence */
/* prompt the user to type in a key to unbind */ /* prompt the user to type in a key to unbind */
mloutstr( "unbind-key: ") ; mlwrite(": unbind-key ");
/* get the command sequence to unbind */ /* get the command sequence to unbind */
int c = getckey( FALSE) ; /* get a command sequence */ c = getckey(FALSE); /* get a command sequence */
if( c == ~0)
return invalidkey() ;
/* change it to something we can print as well */ /* change it to something we can print as well */
/* and dump it out */ cmdstr(c, &outseq[0]);
ostring( cmdstr( c, outseq)) ;
/* prefix key sequence can't be undound, just redefined */ /* and dump it out */
if( c == reptc || c == abortc) ostring(outseq);
return mloutfail( "(Can't unbind prefix)") ;
/* if it isn't bound, bitch */ /* if it isn't bound, bitch */
if( delkeybinding( c) == FALSE) if (unbindchar(c) == FALSE) {
return mloutfail( "(Key not bound)") ; mlwrite("(Key not bound)");
return FALSE;
return TRUE ; }
return TRUE;
} }
/* does source include sub? /*
* unbindchar()
*
* int c; command key to unbind
*/
static int unbindchar( unsigned c) {
struct key_tab *ktp; /* pointer into the command table */
struct key_tab *sktp; /* saved pointer into the command table */
int found; /* matched command flag */
/* search the table to see if the key exists */
ktp = &keytab[0];
found = FALSE;
while (ktp->k_fp != NULL) {
if (ktp->k_code == c) {
found = TRUE;
break;
}
++ktp;
}
/* if it isn't bound, bitch */
if (!found)
return FALSE;
/* save the pointer and scan to the end of the table */
sktp = ktp;
while (ktp->k_fp != NULL)
++ktp;
--ktp; /* backup to the last legit entry */
/* copy the last entry to the current one */
sktp->k_code = ktp->k_code;
sktp->k_fp = ktp->k_fp;
/* null out the last one */
ktp->k_code = 0;
ktp->k_fp = NULL;
return TRUE;
}
/* describe bindings
* bring up a fake buffer and list the key bindings
* into it with view mode
*/
int desbind( int f, int n) {
#if APROP
return buildlist( "") ;
}
/* Apropos (List functions that match a substring) */
int apro( int f, int n) {
char *mstring ; /* string to match cmd names to */
int status ; /* status return */
status = newmlarg( &mstring, "Apropos string: ", 0) ;
if( status == TRUE) {
status = buildlist( mstring) ;
free( mstring) ;
} else if( status == FALSE)
status = buildlist( "") ; /* build list of all commands */
return status ;
}
/*
* build a binding list (limited or full)
*
* char *mstring; match string if a partial list, "" matches all
*/
static int buildlist( char *mstring) {
#endif
struct window *wp; /* scanning pointer to windows */
struct key_tab *ktp; /* pointer into the command table */
struct name_bind *nptr; /* pointer into the name binding table */
struct buffer *bp; /* buffer to put binding list into */
char outseq[80]; /* output buffer for keystroke sequence */
/* split the current window to make room for the binding list */
if (splitwind(FALSE, 1) == FALSE)
return FALSE;
/* and get a buffer for it */
bp = bfind("*Binding list*", TRUE, 0);
if (bp == NULL || bclear(bp) == FALSE) {
mlwrite("Can not display binding list");
return FALSE;
}
/* let us know this is in progress */
mlwrite("(Building binding list)");
/* disconect the current buffer */
if (--curbp->b_nwnd == 0) { /* Last use. */
curbp->b_dotp = curwp->w_dotp;
curbp->b_doto = curwp->w_doto;
curbp->b_markp = curwp->w_markp;
curbp->b_marko = curwp->w_marko;
}
/* connect the current window to this buffer */
curbp = bp; /* make this buffer current in current window */
bp->b_mode = 0; /* no modes active in binding list */
bp->b_nwnd++; /* mark us as more in use */
wp = curwp;
wp->w_bufp = bp;
wp->w_linep = bp->b_linep;
wp->w_flag = WFHARD | WFFORCE;
wp->w_dotp = bp->b_dotp;
wp->w_doto = bp->b_doto;
wp->w_markp = NULL;
wp->w_marko = 0;
/* build the contents of this window, inserting it line by line */
for( nptr = &names[ 0] ; nptr->n_func != NULL ; nptr++) {
int cpos ; /* current position to use in outseq */
#if APROP
/* if we are executing an apropos command..... */
/* and current string doesn't include the search string */
if( *mstring && strinc( nptr->n_name, mstring) == FALSE)
continue ;
#endif
/* add in the command name */
strncpy( outseq, nptr->n_name, sizeof outseq - 1) ;
outseq[ sizeof outseq - 1] = '\0' ;
cpos = strlen(outseq);
/* search down any keys bound to this */
ktp = &keytab[0];
while (ktp->k_fp != NULL) {
if (ktp->k_fp == nptr->n_func) {
/* padd out some spaces */
while (cpos < 28)
outseq[cpos++] = ' ';
/* add in the command sequence */
cmdstr(ktp->k_code, &outseq[cpos]);
strcat(outseq, "\n");
/* and add it as a line into the buffer */
if (linstr(outseq) != TRUE)
return FALSE;
cpos = 0; /* and clear the line */
}
++ktp;
}
/* if no key was bound, we need to dump it anyway */
if (cpos > 0) {
outseq[cpos++] = '\n';
outseq[cpos] = 0;
if (linstr(outseq) != TRUE)
return FALSE;
}
}
curwp->w_bufp->b_mode |= MDVIEW; /* put this buffer view mode */
curbp->b_flag &= ~BFCHG; /* don't flag this as a change */
wp->w_dotp = lforw(bp->b_linep); /* back to the beginning */
wp->w_doto = 0;
wp = wheadp; /* and update ALL mode lines */
while (wp != NULL) {
wp->w_flag |= WFMODE;
wp = wp->w_wndp;
}
mlwrite(""); /* clear the mode line */
return TRUE;
}
#if APROP
/*
* does source include sub?
* *
* char *source; string to search in * char *source; string to search in
* char *sub; substring to look for * char *sub; substring to look for
*/ */
static boolean strinc( const char *source, const char *sub) { static int strinc( char *source, char *sub) {
/* for each character in the source string */ /* for each character in the source string */
for( ; *source ; source++) { for( ; *source ; source++) {
const char *nxtsp ; /* next ptr into source */ char *nxtsp ; /* next ptr into source */
const char *tp ; /* ptr into substring */ char *tp ; /* ptr into substring */
nxtsp = source; nxtsp = source;
@ -225,283 +428,214 @@ static boolean strinc( const char *source, const char *sub) {
return FALSE ; return FALSE ;
} }
#endif
/*
/* describe bindings * get a command key sequence from the keyboard
* bring up a fake buffer and list the key bindings
* into it with view mode
*/
BINDABLE( desbind) {
return buildlist( "") ;
}
/* Apropos (List functions that match a substring) */
BINDABLE( apro) {
char *mstring ; /* string to match cmd names to */
int status = newmlarg( &mstring, "apropos: ", 0) ;
if( status == TRUE) {
status = buildlist( mstring) ;
free( mstring) ;
} else if( status == FALSE)
status = buildlist( "") ; /* build list of all commands */
return status ;
}
/* build a binding list (limited or full)
*
* char *mstring; match string if a partial list, "" matches all
*/
static int buildlist( char *mstring) {
#define PADDING 28
char outseq[ PADDING + 8] ; /* output buffer for command + keystroke */
/* split the current window to make room for the binding list */
if( wheadp->w_wndp == NULL /* One window */
&& splitwind( FALSE, 1) == FALSE) /* Split it */
return FALSE ;
/* and get a buffer for it */
buffer_p bp = bfind( "*Binding list*", TRUE, 0) ;
if( bp == NULL || bclear( bp) == FALSE)
return mloutfail( "Can't display binding list") ;
/* let us know this is in progress */
mloutstr( "(Building binding list)") ;
/* disconnect the current buffer */
if( --curbp->b_nwnd == 0) { /* Last use. */
curbp->b_dotp = curwp->w_dotp ;
curbp->b_doto = curwp->w_doto ;
curbp->b_markp = curwp->w_markp ;
curbp->b_marko = curwp->w_marko ;
}
/* connect the current window to this buffer */
curbp = bp ; /* make this buffer current in current window */
bp->b_mode = 0 ; /* no modes active in binding list */
bp->b_nwnd++ ; /* mark us as more in use */
window_p wp = curwp ;
wp->w_bufp = bp ;
wp->w_linep = bp->b_linep ;
wp->w_flag = WFHARD | WFFORCE ;
wp->w_dotp = bp->b_dotp ;
wp->w_doto = bp->b_doto ;
wp->w_markp = NULL ;
wp->w_marko = 0 ;
/* build the contents of this window, inserting it line by line */
for( nbind_p nptr = names ; nptr->n_func != NULL ; nptr++) {
int cpos ; /* current position to use in outseq */
/* if we are executing an apropos command..... */
/* and current string doesn't include the search string */
if( *mstring && strinc( bind_name( nptr), mstring) == FALSE)
continue ;
/* add in the command name */
mystrscpy( outseq, bind_name( nptr), sizeof outseq) ;
cpos = strlen( outseq) ;
/* search down any keys bound to this */
for( kbind_p ktp = keytab ; ktp->k_code != 0 ; ktp++) {
if( ktp->k_nbp == nptr) {
/* padd out some spaces */
while( cpos < PADDING)
outseq[ cpos++] = ' ' ;
/* add in the command sequence */
cmdstr( ktp->k_code, &outseq[ cpos]) ;
strcat( outseq, "\n") ;
/* and add it as a line into the buffer */
if( linstr( outseq) != TRUE)
return FALSE ;
cpos = 0 ; /* and clear the line */
}
}
/* if no key was bound, we need to dump it anyway */
if( cpos > 0) {
outseq[ cpos++] = '\n';
outseq[ cpos] = 0;
if( linstr( outseq) != TRUE)
return FALSE ;
}
}
bp->b_mode |= MDVIEW ; /* put this buffer view mode */
bp->b_flag &= ~BFCHG ; /* don't flag this as a change */
wp->w_dotp = lforw( bp->b_linep) ; /* back to the beginning */
wp->w_doto = 0 ;
upmode() ; /* and update ALL mode lines */
mloutstr( "") ; /* clear the mode line */
return TRUE ;
}
/* get a command key sequence from the keyboard
* *
* int mflag; going for a meta sequence? * int mflag; going for a meta sequence?
* returns ~0 on failure
*/ */
static unsigned int getckey( int mflag) { static unsigned int getckey( int mflag) {
unsigned int c ; /* character fetched */ unsigned int c ; /* character fetched */
/* check to see if we are executing a command line */ /* check to see if we are executing a command line */
if( clexec) { if( clexec) {
char *tok = getnewtokval() ; /* get the next token */ char *tok ; /* command incoming */
if( tok == NULL)
c = ~0 ; /* return invalid key on failure */ tok = getnewtokval() ; /* get the next token */
else { if( tok == NULL)
c = stock( tok) ; c = 0 ; /* return dummy key on failure */
free( tok) ; else {
} c = stock( tok) ;
} else { /* or the normal way */ free( tok) ;
if( mflag) }
c = get1key() ; } else { /* or the normal way */
else if( mflag)
c = getcmd() ; c = get1key() ;
} else
c = getcmd() ;
}
return c ; return c ;
} }
/*
/* execute the startup file * execute the startup file
* *
* char *fname; name of startup file (null if default) * char *fname; name of startup file (null if default)
*/ */
int startup( const char *fname) { int startup( const char *fname) {
if( !fname || *fname == 0) /* use default if empty parameter */ if( !fname || *fname == 0) /* use default if empty parameter */
fname = rcfname ; fname = rcfname ;
fname = flook( fname, TRUE) ; /* look up the startup file */ fname = flook( fname, TRUE) ; /* look up the startup file */
if( fname == NULL) /* if it isn't around, don't sweat it */ if( fname == NULL) /* if it isn't around, don't sweat it */
return TRUE ; return TRUE ;
return dofile( fname) ; /* otherwise, execute the sucker */ return dofile( fname) ; /* otherwise, execute the sucker */
} }
/*
/* change a key command to a string we can print out * change a key command to a string we can print out
* *
* int c; sequence to translate * int c; sequence to translate
* char *seq; destination string for sequence * char *seq; destination string for sequence
*/ */
static char *cmdstr( unsigned c, char *seq) { static void cmdstr( int c, char *seq) {
char *ptr = seq ; /* pointer into current position in sequence */ char *ptr; /* pointer into current position in sequence */
/* apply meta sequence if needed */ ptr = seq;
if( c & META) {
/* apply meta sequence if needed */
if (c & META) {
*ptr++ = 'M'; *ptr++ = 'M';
*ptr++ = '-'; *ptr++ = '-';
} }
/* apply ^X sequence if needed */ /* apply ^X sequence if needed */
if( c & CTLX) { if (c & CTLX) {
if( ctlxc & CTL_) *ptr++ = '^';
*ptr++ = '^' ; *ptr++ = 'X';
*ptr++ = ctlxc & ~PRFXMASK ;
} }
/* apply control sequence if needed */ /* apply SPEC sequence if needed */
if( c & CTL_) if (c & SPEC) {
*ptr++ = '^' ; *ptr++ = 'F';
*ptr++ = 'N';
/* apply SPEC sequence if needed */
if( c & SPEC) {
*ptr++ = 'F' ;
*ptr++ = 'N' ;
} }
/* and output the final sequence */ /* apply control sequence if needed */
ptr += unicode_to_utf8( c & ~PRFXMASK, ptr) ; if (c & CONTROL) {
*ptr = 0 ; /* terminate the string */ *ptr++ = '^';
return seq ; }
/* and output the final sequence */
*ptr++ = c & 255; /* strip the prefixes */
*ptr = 0; /* terminate the string */
} }
/*
* This function looks a key binding up in the binding table
*
* int c; key to find what is bound to it
*/
fn_t getbind( unsigned c) {
struct key_tab *ktp;
static const char *getfname( unsigned keycode, const char *failmsg) { ktp = &keytab[0]; /* Look in key table. */
/* takes a key code and gets the name of the function bound to it */ while (ktp->k_fp != NULL) {
kbind_p kbp = getkeybinding( keycode) ; if (ktp->k_code == c)
if( kbp->k_code == 0) return ktp->k_fp;
return failmsg ; ++ktp;
}
const char *found = bind_name( kbp->k_nbp) ; /* no such binding */
assert( *found) ; return NULL;
return found ;
} }
/*
* getfname:
* This function takes a ptr to function and gets the name
* associated with it.
*/
static char *getfname(fn_t func)
{
struct name_bind *nptr; /* pointer into the name binding table */
/* stock: /* skim through the table, looking for a match */
nptr = &names[0];
while (nptr->n_func != NULL) {
if (nptr->n_func == func)
return nptr->n_name;
++nptr;
}
return NULL;
}
/*
* match fname to a function in the names table
* and return any match or NULL if none
*
* char *fname; name to attempt to match
*/
int (*fncmatch(char *fname)) (int, int)
{
struct name_bind *ffp; /* pointer to entry in name binding table */
/* scan through the table, returning any match */
ffp = &names[0];
while (ffp->n_func != NULL) {
if (strcmp(fname, ffp->n_name) == 0)
return ffp->n_func;
++ffp;
}
return NULL;
}
/*
* stock:
* String key name TO Command Key * String key name TO Command Key
* *
* char *keyname; name of key to translate to Command key form * char *keyname; name of key to translate to Command key form
* fmt: [M-|^X][^][FN]X
* returns ~0 on invalid sequence
*/ */
static unsigned int stock( char *keyname) { static unsigned int stock( char *keyname) {
/* parse it up */ unsigned int c; /* key sequence to return */
unsigned c = 0 ;
/* first, the prefix META or ^X */ /* parse it up */
if( *keyname == 'M' && keyname[ 1] == '-') { c = 0;
c = META ;
keyname += 2 ; /* first, the META prefix */
} else if( *keyname == '^' && keyname[ 1] == 'X') { if (*keyname == 'M' && *(keyname + 1) == '-') {
c = CTLX ; c = META;
keyname += 2 ; keyname += 2;
} }
/* a control char? */ /* next the function prefix */
if( *keyname == '^' && keyname[ 1] != 0) { if (*keyname == 'F' && *(keyname + 1) == 'N') {
c |= CTL_ ; c |= SPEC;
++keyname ; keyname += 2;
} }
/* next the function prefix */ /* control-x as well... (but not with FN) */
if( *keyname == 'F' && keyname[ 1] == 'N') { if (*keyname == '^' && *(keyname + 1) == 'X' && !(c & SPEC)) {
c |= SPEC ; c |= CTLX;
keyname += 2 ; keyname += 2;
}
/* a control char? */
if (*keyname == '^' && *(keyname + 1) != 0) {
c |= CONTROL;
++keyname;
}
if (*keyname < 32) {
c |= CONTROL;
*keyname += 'A';
} }
/* only one character left to parse */
if( !*keyname || keyname[1])
return ~0 ;
/* only way to redefine ^X is by quoting binary value */
if( *keyname < 32 || *keyname == 0x7F) {
c |= CTL_ ;
*keyname ^= 0x40 ;
} else if( c && !(c & SPEC)
&& *keyname >= 'a' && *keyname <= 'z')
/* make sure we are not lower case (not with function keys) */ /* make sure we are not lower case (not with function keys) */
*keyname -= 32 ; if (*keyname >= 'a' && *keyname <= 'z' && !(c & SPEC))
*keyname -= 32;
/* the final sequence... */ /* the final sequence... */
c |= *keyname & 0xFFU ; c |= *keyname & 0xFFU ;
return c ; return c;
} }
/*
/* string key name to binding name.... * string key name to binding name....
* *
* char *skey; name of key to get binding for * char *skey; name of keey to get binding for
*/ */
const char *transbind( char *skey) { char *transbind(char *skey)
static const char failmsg[] = "ERROR" ; {
char *bindname;
unsigned c = stock( skey) ; bindname = getfname(getbind(stock(skey)));
if( c == (unsigned) ~0) if (bindname == NULL)
return failmsg ; bindname = "ERROR";
else
return getfname( c, failmsg) ; return bindname;
} }
/* end of bind.c */

28
bind.h
View File

@ -1,21 +1,23 @@
/* bind.h -- bindable functions dealing with name and key bindings */
#ifndef _BIND_H_ #ifndef _BIND_H_
#define _BIND_H_ #define _BIND_H_
#include "names.h" /* BINDABLE() */ #define APROP 1 /* Add code for Apropos command */
/* Bindable uEMACS functions */ #if APROP
BINDABLE( apro) ; int apro( int f, int n) ;
BINDABLE( bindtokey) ; #endif
BINDABLE( desbind) ;
BINDABLE( deskey) ;
BINDABLE( help) ;
BINDABLE( unbindkey) ;
/* Some global fuction declarations. */
typedef int (*fn_t)(int, int);
int help( int f, int n) ;
int deskey( int f, int n) ;
int bindtokey( int f, int n) ;
int unbindkey( int f, int n) ;
int desbind( int f, int n) ;
int startup( const char *fname) ; int startup( const char *fname) ;
fn_t getbind( unsigned keycode) ;
/* find a key to function association in the key to function mapping table */ fn_t fncmatch( char *) ;
const char *transbind( char *skey) ; /* by string representation of key */ char *transbind( char *skey) ;
#endif #endif
/* end of bind.h */

View File

@ -1,129 +1,170 @@
/* bindable.c -- implements bindable.h */ /* bindable.h -- implements bindable.c */
#include "bindable.h" #include "bindable.h"
#include <stdlib.h> #include <stdlib.h>
#include "defines.h" #include "defines.h"
#include "buffer.h" #include "buffer.h"
#include "display.h" /* vttidy() */ #include "display.h"
#include "estruct.h"
#include "file.h" #include "file.h"
#include "input.h" #include "input.h"
#include "lock.h" #include "lock.h"
#include "mlout.h" #include "mlout.h"
#include "terminal.h" #include "terminal.h"
/*
/* Fancy quit command, as implemented by Norm. If any buffer has changed * Fancy quit command, as implemented by Norm. If the any buffer has
do a write on that buffer and exit emacs, otherwise simply exit. * changed do a write on that buffer and exit emacs, otherwise simply exit.
*/ */
BINDABLE( quickexit) { int quickexit(int f, int n)
buffer_p oldcb = curbp ; /* save in case we fail */ {
for( buffer_p bp = bheadp ; bp != NULL ; bp = bp->b_bufp) { struct buffer *bp; /* scanning pointer to buffers */
if( (bp->b_flag & (BFCHG | BFTRUNC | BFINVS)) == BFCHG) { struct buffer *oldcb; /* original current buffer */
/* Changed, Not truncated and real buffer */ int status;
curbp = bp ; /* make that buffer cur */
mloutfmt( "(Saving %s)", bp->b_fname) ;
int status = filesave( f, n) ;
if( status != TRUE) {
curbp = oldcb ; /* restore curbp */
return status ;
}
}
}
return quit( f, n) ; /* conditionally quit */ oldcb = curbp; /* save in case we fail */
bp = bheadp;
while (bp != NULL) {
if ((bp->b_flag & BFCHG) != 0 /* Changed. */
&& (bp->b_flag & BFTRUNC) == 0 /* Not truncated P.K. */
&& (bp->b_flag & BFINVS) == 0) { /* Real. */
curbp = bp; /* make that buffer cur */
mloutfmt( "(Saving %s)", bp->b_fname) ;
#if PKCODE
#else
mloutstr( "\n") ;
#endif
if ((status = filesave(f, n)) != TRUE) {
curbp = oldcb; /* restore curbp */
return status;
}
}
bp = bp->b_bufp; /* on to the next buffer */
}
quit(f, n); /* conditionally quit */
return TRUE;
} }
/*
/* Quit command. If an argument, always quit. Otherwise confirm if a buffer * Quit command. If an argument, always quit. Otherwise confirm if a buffer
* has been changed and not written out. Normally bound to "C-X C-C". * has been changed and not written out. Normally bound to "C-X C-C".
*/ */
BINDABLE( quit) { int quit(int f, int n)
int s ; /* status of user query */ {
int s;
if( f != FALSE /* Argument forces it. */ if (f != FALSE /* Argument forces it. */
|| anycb() == FALSE /* All buffers clean. */ || anycb() == FALSE /* All buffers clean. */
/* User says it's OK. */ /* User says it's OK. */
|| (s = mlyesno( "Modified buffers exist. Leave anyway")) == TRUE) { || (s =
#if (FILOCK && BSD) || SVR4 mlyesno("Modified buffers exist. Leave anyway")) == TRUE) {
if( lockrel() != TRUE) { #if (FILOCK && BSD) || SVR4
TTputc('\n') ; if (lockrel() != TRUE) {
TTputc('\r') ; TTputc('\n');
TTclose() ; TTputc('\r');
TTkclose() ; TTclose();
exit( EXIT_FAILURE) ; TTkclose();
} exit( EXIT_FAILURE) ;
}
#endif #endif
vttidy() ; vttidy();
if( f) if (f)
exit( n) ; exit(n);
else else
exit( EXIT_SUCCESS) ; exit( EXIT_SUCCESS) ;
} }
mloutstr( "") ;
mloutstr( "") ; return s;
return s ;
} }
/*
/* Begin a keyboard macro. * Begin a keyboard macro.
* Error if not at the top level in keyboard processing. Set up variables and * Error if not at the top level in keyboard processing. Set up variables and
* return. * return.
*/ */
BBINDABLE( ctlxlp) { int ctlxlp(int f, int n)
if( kbdmode != STOP) {
return mloutfail( "%Macro already active") ; if (kbdmode != STOP) {
mloutstr( "%Macro already active") ;
mloutstr( "(Start macro)") ; return FALSE;
kbdptr = kbdm ; }
kbdend = kbdptr ; mloutstr( "(Start macro)") ;
kbdmode = RECORD ; kbdptr = &kbdm[0];
return TRUE ; kbdend = kbdptr;
kbdmode = RECORD;
return TRUE;
} }
/*
/* End keyboard macro. Check for the same limit conditions as the above * End keyboard macro. Check for the same limit conditions as the above
* routine. Set up the variables and return to the caller. * routine. Set up the variables and return to the caller.
*/ */
BBINDABLE( ctlxrp) { int ctlxrp(int f, int n)
if( kbdmode == STOP) {
return mloutfail( "%Macro not active") ; if (kbdmode == STOP) {
mloutstr( "%Macro not active") ;
if (kbdmode == RECORD) { return FALSE;
mloutstr( "(End macro)") ; }
kbdmode = STOP; if (kbdmode == RECORD) {
} mloutstr( "(End macro)") ;
kbdmode = STOP;
return TRUE ; }
return TRUE;
} }
/*
/* Execute a macro. * Execute a macro.
* The command argument is the number of times to loop. Quit as soon as a * The command argument is the number of times to loop. Quit as soon as a
* command gets an error. Return TRUE if all ok, else FALSE. * command gets an error. Return TRUE if all ok, else FALSE.
*/ */
BBINDABLE( ctlxe) { int ctlxe(int f, int n)
if( kbdmode != STOP) {
return mloutfail( "%Macro already active") ; if (kbdmode != STOP) {
mloutstr( "%Macro already active") ;
if( n <= 0) return FALSE;
return TRUE ; }
if (n <= 0)
kbdrep = n ; /* remember how many times to execute */ return TRUE;
kbdmode = PLAY ; /* start us in play mode */ kbdrep = n; /* remember how many times to execute */
kbdptr = kbdm ; /* at the beginning */ kbdmode = PLAY; /* start us in play mode */
return TRUE ; kbdptr = &kbdm[0]; /* at the beginning */
return TRUE;
} }
/*
/* abort: * Abort.
* Beep the beeper. Kill off any keyboard macro, etc., that is in progress. * Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
* Sometimes called as a routine, to do general aborting of stuff. * Sometimes called as a routine, to do general aborting of stuff.
*/ */
BINDABLE( ctrlg) { int ctrlg( int f, int n) {
kbdmode = STOP ; kbdmode = STOP ;
mloutfmt( "%B(Aborted)") ; mloutfmt( "%B(Aborted)") ;
return ABORT ; return ABORT ;
} }
/* end of bindable.c */ /* user function that does NOTHING */
int nullproc(int f, int n)
{
return TRUE;
}
/* dummy function for binding to meta prefix */
int metafn(int f, int n)
{
return TRUE;
}
/* dummy function for binding to control-x prefix */
int cex(int f, int n)
{
return TRUE;
}
/* dummy function for binding to universal-argument */
int unarg(int f, int n)
{
return TRUE;
}

View File

@ -1,16 +1,11 @@
/* bindable.h -- misc bindable functions */
#ifndef _BINDABLE_H_
#define _BINDABLE_H_
#include "names.h" /* BINDABLE() */
/* functions that can be bound to keys or procedure names */ /* functions that can be bound to keys or procedure names */
BBINDABLE( ctlxe) ; int quickexit( int f, int n) ;
BBINDABLE( ctlxlp) ; int quit( int f, int n) ;
BBINDABLE( ctlxrp) ; int ctlxlp( int f, int n) ;
BINDABLE( ctrlg) ; /* ABORT */ int ctlxrp( int f, int n) ;
BINDABLE( quickexit) ; int ctlxe( int f, int n) ;
BINDABLE( quit) ; int ctrlg( int f, int n) ;
int nullproc( int f, int n) ;
#endif int metafn( int f, int n) ;
/* end of bindable.h */ int cex( int f, int n) ;
int unarg( int f, int n) ;

View File

@ -1,60 +0,0 @@
## blindmaz.cmd -- solve maze by walking a left-handed blind mouse
#7 set $seed
# either maze.cmd, sharpmaz.cmd or floodmaz.cmd
execute-file floodmaz.cmd
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
set %DY1 1
set %DX2 -1
set %DY2 0
set %DX3 0
set %DY3 -1
set %absD 0 # absolute direction: looking EAST
!while &les %x %stopcol
# 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
set %relD &mod &add %relD 1 4
!endwhile
# else turn around
set %absD &mod &add %absD 2 4 # face back!
:moveon
!endwhile
set $curcol &add %x -1
unmark-buffer

1082
buffer.c

File diff suppressed because it is too large Load Diff

137
buffer.h
View File

@ -1,82 +1,87 @@
/* buffer.h -- buffer type and functions */
#ifndef _BUFFER_H_ #ifndef _BUFFER_H_
#define _BUFFER_H_ #define _BUFFER_H_
#include "line.h" /* line_p */ #include "crypt.h"
#include "names.h" /* BINDABLE() */ #include "line.h"
/* Text is kept in buffers. A buffer header, described below, exists for typedef char fname_t[ 80] ; /* file name type */
every buffer in the system. The buffers are kept in a big list, so that typedef char bname_t[ 16] ; /* buffer name type */
commands that search for a buffer by name can find the buffer header. #define NBUFN sizeof( bname_t)
There is a safe store for the dot and mark in the header, but this is
only valid if the buffer is not being displayed (that is, if "b_nwnd" is
0). The text for the buffer is kept in a circularly linked list of
lines, with a pointer to the header line in "b_linep".
Buffers may be "Inactive" which means the files associated with them #if CRYPT
have not been read in yet. These get read in at "use buffer" time. typedef char ekey_t[ 128] ; /* encryption key type */
#endif
/*
* Text is kept in buffers. A buffer header, described below, exists for every
* buffer in the system. The buffers are kept in a big list, so that commands
* that search for a buffer by name can find the buffer header. There is a
* safe store for the dot and mark in the header, but this is only valid if
* the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for
* the buffer is kept in a circularly linked list of lines, with a pointer to
* the header line in "b_linep".
* Buffers may be "Inactive" which means the files associated with them
* have not been read in yet. These get read in at "use buffer" time.
*/ */
struct buffer {
struct buffer *b_bufp; /* Link to next struct buffer */
struct line *b_dotp; /* Link to "." struct line structure */
struct line *b_markp; /* The same as the above two, */
struct line *b_linep; /* Link to the header struct line */
int b_doto; /* Offset of "." in above struct line */
int b_marko; /* but for the "mark" */
int b_mode; /* editor mode of this buffer */
char b_active; /* window activated flag */
char b_nwnd; /* Count of windows on buffer */
char b_flag; /* Flags */
fname_t b_fname ; /* File name */
bname_t b_bname ; /* Buffer name */
#if CRYPT
ekey_t b_key ; /* current encrypted key */
#endif
};
typedef char fname_t[ 256] ; /* file name type */ extern struct buffer *curbp ; /* Current buffer */
typedef char bname_t[ 16] ; /* buffer name type */ extern struct buffer *bheadp ; /* Head of list of buffers */
extern struct buffer *blistp ; /* Buffer for C-X C-B */
typedef struct buffer { #define BFINVS 0x01 /* Internal invisable buffer */
struct buffer *b_bufp ; /* Link to next struct buffer */ #define BFCHG 0x02 /* Changed since last write */
line_p b_dotp ; /* Link to "." struct line structure */ #define BFTRUNC 0x04 /* buffer was truncated when read */
line_p b_markp ; /* The same as the above two, */
line_p b_linep ; /* Link to the header struct line */
int b_doto ; /* Offset of "." in above struct line */
int b_marko ; /* but for the "mark" */
int b_mode ; /* editor mode of this buffer */
char b_active ; /* window activated flag */
char b_nwnd ; /* Count of windows on buffer */
char b_flag ; /* Flags */
fname_t b_fname ; /* File name */
bname_t b_bname ; /* Buffer name */
} *buffer_p ;
extern buffer_p curbp ; /* Current buffer */ /* mode flags */
extern buffer_p bheadp ; /* Head of list of buffers */ #define NUMMODES 11 /* # of defined modes */
extern buffer_p blistp ; /* Buffer for C-X C-B */
#define BFINVS 0x01 /* Internal invisable buffer */ #define MDWRAP 0x0001 /* word wrap */
#define BFCHG 0x02 /* Changed since last write */ #define MDCMOD 0x0002 /* C indentation and fence match */
#define BFTRUNC 0x04 /* buffer was truncated when read */ #define MDSPELL 0x0004 /* spell error parcing */
#define MDEXACT 0x0008 /* Exact matching for searches */
/* mode flags */ #define MDVIEW 0x0010 /* read-only buffer */
#define NUMMODES 9 /* # of defined modes */ #define MDOVER 0x0020 /* overwrite mode */
#define MDMAGIC 0x0040 /* regular expresions in search */
#define MDWRAP 0x0001 /* word wrap */ #if CRYPT
#define MDCMOD 0x0002 /* C indentation and fence match */ #define MDCRYPT 0x0080 /* encrytion mode active */
#define MDEXACT 0x0004 /* Exact matching for searches */ #endif
#define MDVIEW 0x0008 /* read-only buffer */ #define MDASAVE 0x0100 /* auto-save mode */
#define MDOVER 0x0010 /* overwrite mode */ #define MDUTF8 0x0200 /* utf8 mode */
#define MDMAGIC 0x0020 /* regular expresions in search */ #define MDDOS 0x0400 /* CRLF eol mode */
#define MDASAVE 0x0040 /* auto-save mode */
#define MDUTF8 0x0080 /* utf8 mode */
#define MDDOS 0x0100 /* CRLF eol mode */
extern const char *modename[ NUMMODES] ; /* text names of modes */
extern int gmode ; /* global editor mode */
/* Bindable functions */ extern const char *modename[] ; /* text names of modes */
BINDABLE( killbuffer) ; extern int gmode ; /* global editor mode */
BINDABLE( listbuffers) ;
BINDABLE( namebuffer) ;
BINDABLE( nextbuffer) ;
BINDABLE( unmark) ;
BINDABLE( usebuffer) ;
boolean anycb( void) ; /* Any changed buffer? */
int bclear( buffer_p bp) ; /* empty buffer */
int swbuffer( buffer_p bp) ; /* switch to buffer, make it current */
int zotbuf( buffer_p bp) ; /* remove buffer */
/* Lookup a buffer by name. If not found and create_f is TRUE then create int usebuffer( int f, int n) ;
it with flags set. int nextbuffer( int f, int n) ;
*/ int swbuffer( struct buffer *bp) ;
buffer_p bfind( const char *bname, boolean create_f, int flags) ; int killbuffer( int f, int n) ;
int zotbuf( struct buffer *bp) ;
int namebuffer( int f, int n) ;
int listbuffers( int f, int n) ;
int anycb( void) ;
int bclear( struct buffer *bp) ;
int unmark( int f, int n) ;
/* Lookup a buffer by name. */
struct buffer *bfind( const char *bname, int cflag, int bflag) ;
#endif #endif
/* end of buffer.h */

190
crypt.c Normal file
View File

@ -0,0 +1,190 @@
/* crypt.c -- implements crypt.h */
#include "crypt.h"
/* CRYPT.C
*
* Encryption routines
*
* written by Dana Hoggatt and Daniel Lawrence
*/
#if CRYPT
#include <stdio.h>
static int mod95(int);
/**********
*
* myencrypt - in place encryption/decryption of a buffer
*
* (C) Copyright 1986, Dana L. Hoggatt
* 1216, Beck Lane, Lafayette, IN
*
* When consulting directly with the author of this routine,
* please refer to this routine as the "DLH-POLY-86-B CIPHER".
*
* This routine was written for Dan Lawrence, for use in V3.8 of
* MicroEMACS, a public domain text/program editor.
*
* I kept the following goals in mind when preparing this function:
*
* 1. All printable characters were to be encrypted back
* into the printable range, control characters and
* high-bit characters were to remain unaffected. this
* way, encrypted would still be just as cheap to
* transmit down a 7-bit data path as they were before.
*
* 2. The encryption had to be portable. The encrypted
* file from one computer should be able to be decrypted
* on another computer.
*
* 3. The encryption had to be inexpensive, both in terms
* of speed and space.
*
* 4. The system needed to be secure against all but the
* most determined of attackers.
*
* For encryption of a block of data, one calls myencrypt passing
* a pointer to the data block and its length. The data block is
* encrypted in place, that is, the encrypted output overwrites
* the input. Decryption is totally isomorphic, and is performed
* in the same manner by the same routine.
*
* Before using this routine for encrypting data, you are expected
* to specify an encryption key. This key is an arbitrary string,
* to be supplied by the user. To set the key takes two calls to
* myencrypt(). First, you call
*
* myencrypt(NULL, vector)
*
* This resets all internal control information. Typically (and
* specifically in the case on MICRO-emacs) you would use a "vector"
* of 0. Other values can be used to customize your editor to be
* "incompatable" with the normally distributed version. For
* this purpose, the best results will be obtained by avoiding
* multiples of 95.
*
* Then, you "encrypt" your password by calling
*
* myencrypt(pass, strlen(pass))
*
* where "pass" is your password string. Myencrypt() will destroy
* the original copy of the password (it becomes encrypted),
* which is good. You do not want someone on a multiuser system
* to peruse your memory space and bump into your password.
* Still, it is a better idea to erase the password buffer to
* defeat memory perusal by a more technical snooper.
*
* For the interest of cryptologists, at the heart of this
* function is a Beaufort Cipher. The cipher alphabet is the
* range of printable characters (' ' to '~'), all "control"
* and "high-bit" characters are left unaltered.
*
* The key is a variant autokey, derived from a wieghted sum
* of all the previous clear text and cipher text. A counter
* is used as salt to obiterate any simple cyclic behavior
* from the clear text, and key feedback is used to assure
* that the entire message is based on the original key,
* preventing attacks on the last part of the message as if
* it were a pure autokey system.
*
* Overall security of encrypted data depends upon three
* factors: the fundamental cryptographic system must be
* difficult to compromise; exhaustive searching of the key
* space must be computationally expensive; keys and plaintext
* must remain out of sight. This system satisfies this set
* of conditions to within the degree desired for MicroEMACS.
*
* Though direct methods of attack (against systems such as
* this) do exist, they are not well known and will consume
* considerable amounts of computing time. An exhaustive
* search requires over a billion investigations, on average.
*
* The choice, entry, storage, manipulation, alteration,
* protection and security of the keys themselves are the
* responsiblity of the user.
*
*
* char *bptr; buffer of characters to be encrypted
* unsigned len; number of characters in the buffer
*
**********/
void myencrypt(char *bptr, unsigned len)
{
int cc; /* current character being considered */
static long key = 0; /* 29 bit encipherment key */
static int salt = 0; /* salt to spice up key with */
if (!bptr) { /* is there anything here to encrypt? */
key = len; /* set the new key */
salt = len; /* set the new salt */
return;
}
while (len--) { /* for every character in the buffer */
cc = *bptr; /* get a character out of the buffer */
/* only encipher printable characters */
if ((cc >= ' ') && (cc <= '~')) {
/** If the upper bit (bit 29) is set, feed it back into the key. This
assures us that the starting key affects the entire message. **/
key &= 0x1FFFFFFFL; /* strip off overflow */
if (key & 0x10000000L) {
key ^= 0x0040A001L; /* feedback */
}
/** Down-bias the character, perform a Beaufort encipherment, and
up-bias the character again. We want key to be positive
so that the left shift here will be more portable and the
mod95() faster **/
cc = mod95((int) (key % 95) - (cc - ' ')) + ' ';
/** the salt will spice up the key a little bit, helping to obscure
any patterns in the clear text, particularly when all the
characters (or long sequences of them) are the same. We do
not want the salt to go negative, or it will affect the key
too radically. It is always a good idea to chop off cyclics
to prime values. **/
if (++salt >= 20857) { /* prime modulus */
salt = 0;
}
/** our autokey (a special case of the running key) is being
generated by a wieghted checksum of clear text, cipher
text, and salt. **/
key = key + key + cc + *bptr + salt;
}
*bptr++ = cc; /* put character back into buffer */
}
return;
}
static int mod95(int val)
{
/* The mathematical MOD does not match the computer MOD */
/* Yes, what I do here may look strange, but it gets the
job done, and portably at that. */
while (val >= 9500)
val -= 9500;
while (val >= 950)
val -= 950;
while (val >= 95)
val -= 95;
while (val < 0)
val += 95;
return val;
}
#endif

10
crypt.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _CRYPT_H_
#define _CRYPT_H_
#define CRYPT 1 /* file encryption enabled? */
#if CRYPT
void myencrypt( char *bptr, unsigned len) ;
#endif
#endif

View File

@ -1,63 +1,30 @@
/* defines.h -- customization based on gcc predefined macroes */ /* defines.h -- */
#ifndef __DEFINES_H__ #ifndef __DEFINES_H__
#define __DEFINES_H__ #define __DEFINES_H__
#if __unix__ || (defined(__APPLE__) && defined(__MACH__))
# define UNIX 1
# if __NetBSD__ || __OpenBSD__ || (defined(__APPLE__) && defined(__MACH__))
# 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 */ /* Must define one of
VMS | V7 | USG | BSD | MSDOS
#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
/* De-allocate memory always on exit (if the operating system or main
program can not)
*/ */
#define CLEAN 0 /* de-alloc memory on exit */ #define USG 1
#if CLEAN
# define exit(a) cexit(a)
void cexit( int status) ; #define PKCODE 1
#endif #define SCROLLCODE 1 /* scrolling code P.K. */
#define ENVFUNC 1
#define NSTRING 128 /* # of bytes, string buffers */
#define CONTROL 0x10000000 /* Control flag, or'ed in */
#define META 0x20000000 /* Meta flag, or'ed in */
#define CTLX 0x40000000 /* ^X flag, or'ed in */
#define SPEC 0x80000000 /* special key (function keys) */
/* Actual 380x134 on a 1920x1080 screen in landscape,
if smaller font or portrait orientation limit to 400x150 */
#define MAXCOL 400
#define MAXROW 150
#endif #endif
/* end of predefs.h */
/* end of defines.h */

1936
display.c

File diff suppressed because it is too large Load Diff

View File

@ -1,51 +1,40 @@
/* display.h -- display functionality */
#ifndef _DISPLAY_H_ #ifndef _DISPLAY_H_
#define _DISPLAY_H_ #define _DISPLAY_H_
#include <stdarg.h> #include <stdarg.h>
#include "defines.h" /* UNIX */ #include "estruct.h"
#include "names.h" /* BINDABLE() */
#include "utf8.h" /* unicode_t */
#define MINROWS 3 extern int mpresf ; /* Stuff in message line */
#define MINCOLS 10 extern int scrollcount ; /* number of lines to scroll */
extern int discmd ; /* display command flag */
extern int mpresf ; /* Stuff in message line */ extern int gfcolor ; /* global forgrnd color (white) */
extern int scrollcount ; /* number of lines to scroll */ extern int gbcolor ; /* global backgrnd color (black) */
extern int discmd ; /* display command flag */
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 */
TBINDABLE( upscreen) ;
void vtinit( void) ; void vtinit( void) ;
void vtfree( void) ; void vtfree( void) ;
void vttidy( void) ; void vttidy( void) ;
void update( boolean force_f) ; void vtmove( int row, int col) ;
void updmargin( void) ; int upscreen( int f, int n) ;
int update( int force) ;
void updpos( void) ;
void upddex( void) ;
void updgar( void) ;
int updupd( int force) ;
void upmode( void) ; void upmode( void) ;
void movecursor( int row, int col) ; void movecursor( int row, int col) ;
void mlerase( void) ; void mlerase( void) ;
void vmlwrite( const char *fmt, va_list ap) ; void vmlwrite( const char *fmt, va_list ap) ;
void mlwrite( const char *fmt, ...) ; void mlwrite( const char *fmt, ...) ;
void ostring( const char *s) ;
void echoc( unicode_t c) ;
void echos( const char *s) ;
void rubout( void) ;
void getscreensize( int *widthp, int *heightp) ; void getscreensize( int *widthp, int *heightp) ;
#if UNIX #if UNIX
# include <signal.h> #include <signal.h>
# ifdef SIGWINCH #ifdef SIGWINCH
extern int chg_width, chg_height ; extern int chg_width, chg_height ;
# endif
void sizesignal( int signr) ;
#endif
#endif #endif
#endif #endif
/* end of display.h */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -1,27 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>µEMACS</title>
<style>
body {
width: 1024px ;
margin-left: auto ;
margin-right: auto ;
}
</style>
</head>
<body>
<h1>µEMACS</h1>
<b>µEMACS</b> (ue) based on uEmacs/PK (em) from
<a href="https://git.kernel.org/pub/scm/editors/uemacs/uemacs.git/">kernel.org</a>.
Latest version built and tested on Cygwin, Ubuntu Linux and NetBSD.
<p>
<a href="quick.html">Quick build and install</a>
<p>
<img src="img/ue_425.png" alt="µEMACS sample screenshot">
<hr>© 2020-2024 Renaud Fivet
</body>
</html>

View File

@ -1,115 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Quick µEMACS build and install</title>
<style>
body {
width: 1024px ;
margin-left: auto ;
margin-right: auto ;
}
pre {
background-color: #F3F6FA ;
margin-left: 1% ;
margin-right: 25% ;
}
</style>
</head>
<body>
<h1>Quick µEMACS build and install</h1>
<h2>Dependencies and build environment</h2>
To build µEMACS, you need to have gcc, GNU make and ncurses development
library installed.
<h2>Checking environment</h2>
gcc and GNU make are often preinstalled with GNU make set as the default
make. Use your favorite package manager to check their availability.
<pre>
% which gcc make
/usr/bin/gcc
/usr/bin/make
% apt list gcc make
gcc/focal,now 4:9.3.0-1ubuntu2 amd64 [installed]
make/focal,now 4.2.1-1.2 amd64 [installed]
</pre>
Use your favorite package manager if they need to be installed.
<pre>% sudo apt install gcc make</pre>
To check that make is actually GNU make:
<pre>
% make --version
GNU Make 4.2.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
</pre>
ncurses development library usually need to be installed. Query your
favorite package manager to check which packages are available for
installation:
<pre>% apt search libncurses</pre>
Use your favorite package manager to install the needed package:
<pre>% sudo apt install libncurses-dev</pre>
On Ubuntu, apt will select the package that matches your architecture
(amd64 or i386).
<h2>Getting the sources</h2>
µEMACS source code is available on
<a href="https://github.com/rfivet/uemacs">github</a> and mirrored at
<a href="https://git.sdf.org/rfivet/uemacs">git.sdf.org</a>. From github, you
can either clone the
<a href="https://github.com/rfivet/uemacs.git">git repository</a> or download a
<a href="https://github.com/rfivet/uemacs/archive/master.zip">zip archive</a>.
<p>
Move to working directory and clone:
<pre>
% mkdir ~/Projects
% cd ~/Projects
% git clone https://github.com/rfivet/uemacs.git
</pre>
<h2>Building</h2>
<pre>
% cd ~/Projects/uemacs
% make
</pre>
If <b>GNU make</b> is not set as the default make you will have to call it
explicitly
<pre>% gmake</pre>
<h2>Testing</h2>
Start the editor:
<pre>% ./ue</pre>
To leave the editor type CTL-X CTL-C
<p>
Execute a sample script:
<pre>% ./ue -x screensize.cmd</pre>
<img src="img/ue_screensize.png" alt="Executing script screensize.cmd">
<hr>© 2020-2024 Renaud Fivet
</body>
</html>

441
ebind.c Normal file
View File

@ -0,0 +1,441 @@
/* ebind.c -- implements ebind.h */
#include "ebind.h"
/* ebind.c
*
* Initial default key to function bindings
*
* Modified by Petri Kutvonen
*/
#include <stdlib.h>
#include "basic.h"
#include "bind.h"
#include "estruct.h"
#include "bindable.h"
#include "buffer.h"
#include "eval.h"
#include "exec.h"
#include "file.h"
#include "isearch.h"
#include "line.h"
#include "random.h"
#include "region.h"
#include "search.h"
#include "spawn.h"
#include "window.h"
#include "word.h"
/*
* Command table.
* This table is *roughly* in ASCII order, left to right across the
* characters of the command. This explains the funny location of the
* control-X commands.
*/
struct key_tab keytab[NBINDS] = {
{CONTROL | 'A', gotobol}
,
{CONTROL | 'B', backchar}
,
{CONTROL | 'C', insspace}
,
{CONTROL | 'D', forwdel}
,
{CONTROL | 'E', gotoeol}
,
{CONTROL | 'F', forwchar}
,
{CONTROL | 'G', ctrlg}
,
{CONTROL | 'H', backdel}
,
{CONTROL | 'I', insert_tab}
,
{CONTROL | 'J', indent}
,
{CONTROL | 'K', killtext}
,
{CONTROL | 'L', redraw}
,
{CONTROL | 'M', insert_newline}
,
{CONTROL | 'N', forwline}
,
{CONTROL | 'O', openline}
,
{CONTROL | 'P', backline}
,
{CONTROL | 'Q', quote}
,
{CONTROL | 'R', backsearch}
,
{CONTROL | 'S', forwsearch}
,
{CONTROL | 'T', twiddle}
,
{CONTROL | 'U', unarg}
,
{CONTROL | 'V', forwpage}
,
{CONTROL | 'W', killregion}
,
{CONTROL | 'X', cex}
,
{CONTROL | 'Y', yank}
,
{CONTROL | 'Z', backpage}
,
{CONTROL | ']', metafn}
,
{CTLX | CONTROL | 'B', listbuffers}
,
{CTLX | CONTROL | 'C', quit}
, /* Hard quit. */
#if PKCODE & AEDIT
{CTLX | CONTROL | 'A', detab}
,
#endif
#if PKCODE
{CTLX | CONTROL | 'D', filesave}
, /* alternative */
#else
#if AEDIT
{CTLX | CONTROL | 'D', detab}
,
#endif
#endif
#if AEDIT
{CTLX | CONTROL | 'E', entab}
,
#endif
{CTLX | CONTROL | 'F', filefind}
,
{CTLX | CONTROL | 'I', insfile}
,
{CTLX | CONTROL | 'L', lowerregion}
,
{CTLX | CONTROL | 'M', delmode}
,
{CTLX | CONTROL | 'N', mvdnwind}
,
{CTLX | CONTROL | 'O', deblank}
,
{CTLX | CONTROL | 'P', mvupwind}
,
{CTLX | CONTROL | 'R', fileread}
,
{CTLX | CONTROL | 'S', filesave}
,
#if AEDIT
{CTLX | CONTROL | 'T', trim}
,
#endif
{CTLX | CONTROL | 'U', upperregion}
,
{CTLX | CONTROL | 'V', viewfile}
,
{CTLX | CONTROL | 'W', filewrite}
,
{CTLX | CONTROL | 'X', swapmark}
,
{CTLX | CONTROL | 'Z', shrinkwind}
,
{CTLX | '?', deskey}
,
{CTLX | '!', spawn}
,
{CTLX | '@', pipecmd}
,
{CTLX | '#', filter_buffer}
,
{CTLX | '$', execprg}
,
{CTLX | '=', showcpos}
,
{CTLX | '(', ctlxlp}
,
{CTLX | ')', ctlxrp}
,
{CTLX | '^', enlargewind}
,
{CTLX | '0', delwind}
,
{CTLX | '1', onlywind}
,
{CTLX | '2', splitwind}
,
{CTLX | 'A', setvar}
,
{CTLX | 'B', usebuffer}
,
{CTLX | 'C', spawncli}
,
#if BSD | __hpux | SVR4
{CTLX | 'D', bktoshell}
,
#endif
{CTLX | 'E', ctlxe}
,
{CTLX | 'F', setfillcol}
,
{CTLX | 'K', killbuffer}
,
{CTLX | 'M', setemode}
,
{CTLX | 'N', filename}
,
{CTLX | 'O', nextwind}
,
{CTLX | 'P', prevwind}
,
#if PKCODE
{CTLX | 'Q', quote}
, /* alternative */
#endif
#if ISRCH
{CTLX | 'R', risearch}
,
{CTLX | 'S', fisearch}
,
#endif
{CTLX | 'W', resize}
,
{CTLX | 'X', nextbuffer}
,
{CTLX | 'Z', enlargewind}
,
#if WORDPRO
{META | CONTROL | 'C', wordcount}
,
#endif
#if PKCODE
{META | CONTROL | 'D', newsize}
,
#endif
#if PROC
{META | CONTROL | 'E', execproc}
,
#endif
#if CFENCE
{META | CONTROL | 'F', getfence}
,
#endif
{META | CONTROL | 'H', delbword}
,
{META | CONTROL | 'K', unbindkey}
,
{META | CONTROL | 'L', reposition}
,
{META | CONTROL | 'M', delgmode}
,
{META | CONTROL | 'N', namebuffer}
,
{META | CONTROL | 'R', qreplace}
,
{META | CONTROL | 'S', newsize}
,
{META | CONTROL | 'T', newwidth}
,
{META | CONTROL | 'V', scrnextdw}
,
#if WORDPRO
{META | CONTROL | 'W', killpara}
,
#endif
{META | CONTROL | 'Z', scrnextup}
,
{META | ' ', setmark}
,
{META | '?', help}
,
{META | '!', reposition}
,
{META | '.', setmark}
,
{META | '>', gotoeob}
,
{META | '<', gotobob}
,
{META | '~', unmark}
,
#if APROP
{META | 'A', apro}
,
#endif
{META | 'B', backword}
,
{META | 'C', capword}
,
{META | 'D', delfword}
,
#if CRYPT
{META | 'E', set_encryption_key}
,
#endif
{META | 'F', forwword}
,
{META | 'G', gotoline}
,
#if PKCODE
#if WORDPRO
{META | 'J', justpara}
,
#endif
#endif
{META | 'K', bindtokey}
,
{META | 'L', lowerword}
,
{META | 'M', setgmode}
,
#if WORDPRO
{META | 'N', gotoeop}
,
{META | 'P', gotobop}
,
{META | 'Q', fillpara}
,
#endif
{META | 'R', sreplace}
,
#if PKCODE
{META | 'S', forwhunt}
,
#else
#if BSD
{META | 'S', bktoshell}
,
#endif
#endif
{META | 'U', upperword}
,
{META | 'V', backpage}
,
{META | 'W', copyregion}
,
{META | 'X', namedcmd}
,
{META | 'Z', quickexit}
,
{META | 0x7F, delbword}
,
#if MSDOS
{SPEC | CONTROL | '_', forwhunt}
,
{SPEC | CONTROL | 'S', backhunt}
,
{SPEC | 71, gotobol}
,
{SPEC | 72, backline}
,
{SPEC | 73, backpage}
,
{SPEC | 75, backchar}
,
{SPEC | 77, forwchar}
,
{SPEC | 79, gotoeol}
,
{SPEC | 80, forwline}
,
{SPEC | 81, forwpage}
,
{SPEC | 82, insspace}
,
{SPEC | 83, forwdel}
,
{SPEC | 115, backword}
,
{SPEC | 116, forwword}
,
#if WORDPRO
{SPEC | 132, gotobop}
,
{SPEC | 118, gotoeop}
,
#endif
{SPEC | 84, cbuf1}
,
{SPEC | 85, cbuf2}
,
{SPEC | 86, cbuf3}
,
{SPEC | 87, cbuf4}
,
{SPEC | 88, cbuf5}
,
{SPEC | 89, cbuf6}
,
{SPEC | 90, cbuf7}
,
{SPEC | 91, cbuf8}
,
{SPEC | 92, cbuf9}
,
{SPEC | 93, cbuf10}
,
#if PKCODE
{SPEC | 117, gotoeob}
,
{SPEC | 119, gotobob}
,
{SPEC | 141, gotobop}
,
{SPEC | 145, gotoeop}
,
{SPEC | 146, yank}
,
{SPEC | 147, killregion}
,
#endif
#endif
#if VT220
{SPEC | '1', gotobob /* fisearch */}
, /* VT220 keys */
{SPEC | '2', yank}
,
{SPEC | '3', forwdel /* killregion */}
,
{SPEC | '4', gotoeob /* setmark */}
,
{SPEC | '5', backpage}
,
{SPEC | '6', forwpage}
,
{SPEC | 'A', backline}
,
{SPEC | 'B', forwline}
,
{SPEC | 'C', forwchar}
,
{SPEC | 'D', backchar}
,
{SPEC | 'c', metafn}
,
{SPEC | 'd', backchar}
,
{SPEC | 'e', forwline}
,
{SPEC | 'f', gotobob}
,
{SPEC | 'h', help}
,
{SPEC | 'i', cex}
,
#endif
{0x7F, backdel}
,
/* special internal bindings */
{ SPEC | META | 'W', wrapword }, /* called on word wrap */
{ SPEC | META | 'C', nullproc }, /* every command input */
{ SPEC | META | 'R', nullproc }, /* on file read */
{ SPEC | META | 'X', nullproc }, /* on window change P.K. */
{0, NULL}
};

9
ebind.h Normal file
View File

@ -0,0 +1,9 @@
/* Structure for the table of initial key bindings. */
struct key_tab {
unsigned k_code ; /* Key code */
int (*k_fp)( int, int) ; /* Routine to handle it */
} ;
#define NBINDS 256 /* max # of bound keys */
extern struct key_tab keytab[ NBINDS] ; /* key bind to functions table */

View File

@ -1,4 +1,4 @@
=> µEMACS 4.2 HELP INDEX => uEmacs/PK 4.0 HELP INDEX
.. The very basics .. The very basics
.. Cursor movement .. Cursor movement
.. File commands .. File commands
@ -19,7 +19,7 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
=> THE VERY BASICS => THE VERY BASICS
Notations: ^X means <Ctrl> and X. The <Meta> key is <Esc> on most systems. Notations: ^X means <Ctrl> and X. The <Meta> key is <Esc> on most systems.
Exiting: ^G aborts almost any operation. ^X ^C will get you out of µEMACS. Exiting: ^G aborts almost any operation. ^X ^C will get you out of uEmacs.
A BUFFER is a named area containing a FILE being edited. Many buffers may A BUFFER is a named area containing a FILE being edited. Many buffers may
be active at once. Many WINDOWS may be active at once on the screen. All be active at once. Many WINDOWS may be active at once on the screen. All
@ -37,7 +37,7 @@ Beginning of file ..... Meta < End of file ........... Meta >
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
=> FILE COMMANDS => FILE COMMANDS
Find file ............. ^X ^F Quick exit ............ Meta Z Find file ............. ^X ^F Quick exit ............ Meta Z
View file ............. ^X ^V Exit µEMACS ........... ^X ^C View file ............. ^X ^V Exit emacs ............ ^X ^C
Insert file ........... ^X ^I Insert file ........... ^X ^I
Change file name ...... ^X N Filter buffer ......... ^X # Change file name ...... ^X N Filter buffer ......... ^X #
Save file ............. ^X ^D Save file ............. ^X ^D
@ -111,19 +111,19 @@ Pipe command .......... ^X @ Execute buffer ........ not bound
Search forward ........ Meta S :: End string with Meta. Search forward ........ Meta S :: End string with Meta.
Incremental search .... ^X S :: Search next ^X, stop Meta, cancel ^G. Incremental search .... ^X S :: Search next ^X, stop Meta, cancel ^G.
Search reverse ........ ^R Search reverse ........ ^R
Reverse incremental Hunt forward .......... Alt-S Reverse incremental search Hunt forward .......... Alt-S
search ^X R Hunt backward ......... Alt-R ....................... ^X R Hunt backward ......... Alt-R
Replace string ........ Meta R Replace string ........ Meta R
Query replace string .. Meta ^R :: Yes/no Y/N, replace rest !, cancel ^G. Query replace string .. Meta ^R :: Yes/no Y/N, replace rest !, cancel ^G.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
=> ACCESSING THE OPERATING SYSTEM => ACCESSING THE OPERATING SYSTEM
Quick exit ............ Meta Z :: Write out all changed buffers and exit. Quick exit ............ Meta Z :: Write out all changed buffers and exit.
Exit µEMACS ........... ^X ^C :: Exit without automatic save. Exit emacs ............ ^X ^C :: Exit without automatic save.
I shell ............... ^X C :: Start a new command processor. I shell ............... ^X C :: Start a new command processor.
Shell command ......... ^X ! :: Execute one operating system command. Shell command ......... ^X ! :: Execute one operating system command.
Pipe command .......... ^X @ :: Pipe command results to a new buffer. Pipe command .......... ^X @ :: Pipe command results to a new buffer. *
Filter buffer ......... ^X # :: Filter buffer through a program. Filter buffer ......... ^X # :: Filter buffer through a program. *
Execute program ....... ^X $ :: Execute program ....... ^X $ :: * Not under VMS.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
=> MACRO COMMANDS => MACRO COMMANDS
Begin macro ........... ^X ( Begin macro ........... ^X (
@ -140,7 +140,7 @@ Clear and redraw ...... ^L Exchange point and mark ^X ^X
Redraw display ........ Meta ^L Redraw display ........ Meta ^L
Execute named command . Meta X Insert string ......... not bound Execute named command . Meta X Insert string ......... not bound
Execute command line .. not bound Overwrite string ...... not bound Execute command line .. not bound Overwrite string ...... not bound
Wrap word ............. not bound Set encryption key .... Meta E Wrap word ............. not bound
Count words ........... Meta ^C Update screen ......... not bound Count words ........... Meta ^C Update screen ......... not bound
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
=> SYSTEM VARIABLES => SYSTEM VARIABLES
@ -164,9 +164,9 @@ Page overlap .......... $overlap :: # lines, default 0, 0 = 1/3 page
=> FILE NAME COMPLETION => FILE NAME COMPLETION
File name completion can be used with all file commands (find-file, File name completion can be used with all file commands (find-file,
view-file, ...). It is invoked by a <Space> or <Tab>. If there exist more view-file, ...) but it works only under UNIX and MS-DOS. It is invoked
than one possible completions they are displayed one by one. If the file by a <Space> or <Tab>. If there exist more than one possible completions
name contains wild card characters, the name is expanded instead of simple they are displayed one by one. If the file name contains wild card
completion. Special characters can be entered verbatim by prefixing them characters, the name is expanded instead of simple completion. Special
with ^V (or ^Q). characters can be entered verbatim by prefixing them with ^V (or ^Q).
------------------------------------------------------------------------------- -------------------------------------------------------------------------------

BIN
emacs.pdf

Binary file not shown.

298
emacs.rc
View File

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

303
estruct.h Normal file
View File

@ -0,0 +1,303 @@
#ifndef _ESTRUCT_H_
#define _ESTRUCT_H_
/* 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
#ifdef EGA
#undef EGA
#endif
/* Machine/OS definitions. */
#if defined(AUTOCONF) || defined(MSDOS) || defined(BSD) || defined(SYSV) || defined(VMS)
/* Make an intelligent guess about the target system. */
#if defined(__TURBOC__)
#define MSDOS 1 /* MS/PC DOS 3.1-4.0 with Turbo C 2.0 */
#else
#define MSDOS 0
#endif
#if defined(BSD) || defined(sun) || defined(ultrix) || (defined(vax) && defined(unix)) || 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(__hpux) || defined( __unix__)
#define USG 1 /* System V UNIX */
#else
#define USG 0
#endif
#if defined(VMS) || (defined(vax) && ! defined(unix))
#define VMS 1 /* VAX/VMS */
#else
#define VMS 0
#endif
#define V7 0 /* No more. */
#else
#define MSDOS 1 /* MS-DOS */
#define V7 0 /* V7 UNIX or Coherent or BSD4.2 */
#define BSD 0 /* UNIX BSD 4.2 and ULTRIX */
#define USG 0 /* UNIX system V */
#define VMS 0 /* VAX/VMS */
#endif /*autoconf */
#ifndef AUTOCONF
/* Compiler definitions */
#define UNIX 0 /* a random UNIX compiler */
#define MSC 0 /* MicroSoft C compiler, versions 3 up */
#define TURBO 1 /* Turbo C/MSDOS */
#else
#define UNIX (V7 | BSD | USG)
#define MSC 0
#define TURBO MSDOS
#endif /*autoconf */
/* Debugging options */
#define RAMSIZE 0 /* dynamic RAM memory usage tracking */
#if RAMSIZE
#define RAMSHOW 1 /* auto dynamic RAM reporting */
#endif
#ifndef AUTOCONF
/* Special keyboard definitions */
#define VT220 0 /* Use keypad escapes P.K. */
#define VT100 0 /* Handle VT100 style keypad. */
/* Terminal Output definitions */
#define ANSI 0 /* ANSI escape sequences */
#define VMSVT 0 /* various VMS terminal entries */
#define VT52 0 /* VT52 terminal (Zenith). */
#define TERMCAP 0 /* Use TERMCAP */
#define IBMPC 1 /* IBM-PC CGA/MONO/EGA driver */
#elif defined( MINGW32)
#define VT220 (UNIX | VMS)
#define VT100 0
#define ANSI 0
#define VMSVT 0
#define VT52 0
#define TERMCAP 0
#define IBMPC 0
#else
#define VT220 (UNIX | VMS)
#define VT100 0
#define ANSI 0
#define VMSVT VMS
#define VT52 0
#define TERMCAP UNIX
#define IBMPC MSDOS
#endif /* Autoconf. */
/* Configuration options */
#define CFENCE 1 /* fench matching in CMODE */
#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 */
#define ASCII 1 /* always using ASCII char sequences for now */
#define EBCDIC 0 /* later IBM mainfraim versions will use EBCDIC */
#ifndef AUTOCONF
#define XONXOFF 0 /* don't disable XON-XOFF flow control P.K. */
#define NATIONL 0 /* interprete [,],\,{,},| as characters P.K. */
#else
#define XONXOFF (UNIX | VMS)
#define NATIONL (UNIX | VMS)
#endif /* Autoconf. */
#define PKCODE 1 /* include my extensions P.K., define always */
#define IBMCHR MSDOS /* use IBM PC character set P.K. */
#define SCROLLCODE 1 /* scrolling code P.K. */
/* System dependant library redefinitions, structures and includes. */
#if TURBO
#include <dos.h>
#include <mem.h>
#undef peek
#undef poke
#define peek(a,b,c,d) movedata(a,b,FP_SEG(c),FP_OFF(c),d)
#define poke(a,b,c,d) movedata(FP_SEG(c),FP_OFF(c),a,b,d)
#endif
#if VMS
#define atoi xatoi
#define abs xabs
#define getname xgetname
#endif
#if MSDOS & MSC
#include <dos.h>
#include <memory.h>
#define peek(a,b,c,d) movedata(a,b,FP_SEG(c),FP_OFF(c),d)
#define poke(a,b,c,d) movedata(FP_SEG(c),FP_OFF(c),a,b,d)
#define movmem(a, b, c) memcpy(b, a, c)
#endif
#if VMS
#define unlink(a) delete(a)
#endif
/* Define some ability flags. */
#if IBMPC
#define MEMMAP 1
#else
#define MEMMAP 0
#endif
#if MSDOS | V7 | USG | BSD
#define ENVFUNC 1
#else
#define ENVFUNC 0
#endif
/* Internal defined functions */
#ifdef abs
#undef abs
#endif
/* DIFCASE represents the integer difference between upper
and lower case letters. It is an xor-able value, which is
fortunate, since the relative positions of upper to lower
case letters is the opposite of ascii in ebcdic.
*/
#ifdef islower
#undef islower
#endif
#if PKCODE
#ifdef isupper
#undef isupper
#endif
#endif
#if ASCII
#define DIFCASE 0x20
#if NATIONL
#define LASTUL ']'
#define LASTLL '}'
#else
#define LASTUL 'Z'
#define LASTLL 'z'
#endif
#if IBMCHR
#define isletter(c) (('a' <= c && LASTLL >= c) || ('A' <= c && LASTUL >= c) || (128<=c && c<=167))
#define islower(c) (('a' <= c && LASTLL >= c))
#define isupper(c) (('A' <= c && LASTUL >= c))
#else
#define isletter(c) __isxletter((0xFF & (c)))
#define islower(c) isxlower((0xFF & (c)))
#define isupper(c) isxupper((0xFF & (c)))
#define __isxletter(c) (('a' <= c && LASTLL >= c) || ('A' <= c && LASTUL >= c) || (192<=c /* && c<=255 */))
#define isxlower(c) (('a' <= c && LASTLL >= c) || (224 <= c && 252 >= c))
#define isxupper(c) (('A' <= c && LASTUL >= c) || (192 <= c && 220 >= c))
#endif
#endif
#if EBCDIC
#define DIFCASE 0x40
#define isletter(c) (('a' <= c && 'i' >= c) || ('j' <= c && 'r' >= c) || ('s' <= c && 'z' >= c) || ('A' <= c && 'I' >= c) || ('J' <= c && 'R' >= c) || ('S' <= c && 'Z' >= c))
#define islower(c) (('a' <= c && 'i' >= c) || ('j' <= c && 'r' >= c) || ('s' <= c && 'z' >= c))
#if PKCODE
#define isupper(c) (('A' <= c && 'I' >= c) || ('J' <= c && 'R' >= c) || ('S' <= c && 'Z' >= c))
#endif
#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

718
eval.c

File diff suppressed because it is too large Load Diff

29
eval.h
View File

@ -1,31 +1,30 @@
/* eval.h -- variables and operands evaluation */
#ifndef _EVAL_H_ #ifndef _EVAL_H_
#define _EVAL_H_ #define _EVAL_H_
#include "names.h"
#define DEBUGM 1 /* $debug triggers macro debugging */ #define DEBUGM 1 /* $debug triggers macro debugging */
#if DEBUGM
int mdbugout( char *fmt, ...) ; #if DEBUGM
int mdbugout( char *fmt, ...) ;
#endif #endif
extern int macbug ; /* macro debuging flag */
extern int cmdstatus ; /* last command status */ extern int macbug ; /* macro debuging flag */
extern int rval ; /* return value of a subprocess */ extern int cmdstatus ; /* last command status */
extern unsigned envram ; /* # of bytes current in use by malloc */ extern int rval ; /* return value of a subprocess */
extern long envram ; /* # of bytes current in use by malloc */
int readfirst_f( void) ; int readfirst_f( void) ;
int is_it_cmd( char *token) ; int is_it_cmd( char *token) ;
void varinit( void) ; void varinit( void) ;
const char *getval( char *token) ; int setvar( int f, int n) ;
char *getval( char *token) ;
int stol( char *val) ; int stol( char *val) ;
char *mklower( char *str) ; char *mklower( char *str) ;
int abs( int x) ;
/* Bindable functions */ int clrmes( int f, int n) ;
TBINDABLE( clrmes) ; int writemsg( int f, int n) ;
BINDABLE( setvar) ;
BINDABLE( writemsg) ;
#endif #endif
/* end of eval.h */

1684
exec.c

File diff suppressed because it is too large Load Diff

112
exec.h
View File

@ -1,64 +1,70 @@
/* exec.h -- bindable functions to execute functions, macros and procedures */
#ifndef _EXEC_H_ #ifndef _EXEC_H_
#define _EXEC_H_ #define _EXEC_H_
#include "names.h" #include "retcode.h"
extern boolean clexec ; /* command line execution flag */
int dofile( const char *fname) ; #define PROC 1 /* named procedures */
#if PROC
int storeproc( int f, int n) ;
int execproc( int f, int n) ;
#endif
extern boolean clexec ; /* command line execution flag */
void ue_system( const char *cmd) ;
int namedcmd( int f, int n) ;
int execcmd( int f, int n) ;
void gettoken( char *tok, int maxtoksize) ; void gettoken( char *tok, int maxtoksize) ;
boolean gettokval( char *tok, int maxtoksize) ; boolean gettokval( char *tok, int maxtoksize) ;
char *getnewtokval( void) ; char *getnewtokval( void) ;
int storemac( int f, int n) ;
int execbuf( int f, int n) ;
int execfile( int f, int n) ;
int dofile( const char *fname) ;
/* Bindable functions */ int cbuf1( int f, int n) ;
BINDABLE( execbuf) ; int cbuf2( int f, int n) ;
BINDABLE( execcmd) ; int cbuf3( int f, int n) ;
BINDABLE( execfile) ; int cbuf4( int f, int n) ;
BINDABLE( execproc) ; int cbuf5( int f, int n) ;
BINDABLE( namedcmd) ; int cbuf6( int f, int n) ;
BBINDABLE( storemac) ; int cbuf7( int f, int n) ;
BINDABLE( storeproc) ; int cbuf8( int f, int n) ;
BINDABLE( cbuf1) ; int cbuf9( int f, int n) ;
BINDABLE( cbuf2) ; int cbuf10( int f, int n) ;
BINDABLE( cbuf3) ; int cbuf11( int f, int n) ;
BINDABLE( cbuf4) ; int cbuf12( int f, int n) ;
BINDABLE( cbuf5) ; int cbuf13( int f, int n) ;
BINDABLE( cbuf6) ; int cbuf14( int f, int n) ;
BINDABLE( cbuf7) ; int cbuf15( int f, int n) ;
BINDABLE( cbuf8) ; int cbuf16( int f, int n) ;
BINDABLE( cbuf9) ; int cbuf17( int f, int n) ;
BINDABLE( cbuf10) ; int cbuf18( int f, int n) ;
BINDABLE( cbuf11) ; int cbuf19( int f, int n) ;
BINDABLE( cbuf12) ; int cbuf20( int f, int n) ;
BINDABLE( cbuf13) ; int cbuf21( int f, int n) ;
BINDABLE( cbuf14) ; int cbuf22( int f, int n) ;
BINDABLE( cbuf15) ; int cbuf23( int f, int n) ;
BINDABLE( cbuf16) ; int cbuf24( int f, int n) ;
BINDABLE( cbuf17) ; int cbuf25( int f, int n) ;
BINDABLE( cbuf18) ; int cbuf26( int f, int n) ;
BINDABLE( cbuf19) ; int cbuf27( int f, int n) ;
BINDABLE( cbuf20) ; int cbuf28( int f, int n) ;
BINDABLE( cbuf21) ; int cbuf29( int f, int n) ;
BINDABLE( cbuf22) ; int cbuf30( int f, int n) ;
BINDABLE( cbuf23) ; int cbuf31( int f, int n) ;
BINDABLE( cbuf24) ; int cbuf32( int f, int n) ;
BINDABLE( cbuf25) ; int cbuf33( int f, int n) ;
BINDABLE( cbuf26) ; int cbuf34( int f, int n) ;
BINDABLE( cbuf27) ; int cbuf35( int f, int n) ;
BINDABLE( cbuf28) ; int cbuf36( int f, int n) ;
BINDABLE( cbuf29) ; int cbuf37( int f, int n) ;
BINDABLE( cbuf30) ; int cbuf38( int f, int n) ;
BINDABLE( cbuf31) ; int cbuf39( int f, int n) ;
BINDABLE( cbuf32) ; int cbuf40( int f, int n) ;
BINDABLE( cbuf33) ;
BINDABLE( cbuf34) ;
BINDABLE( cbuf35) ;
BINDABLE( cbuf36) ;
BINDABLE( cbuf37) ;
BINDABLE( cbuf38) ;
BINDABLE( cbuf39) ;
BINDABLE( cbuf40) ;
#endif #endif
/* end of exec.h */

548
execute.c
View File

@ -1,508 +1,108 @@
/* execute.c -- implements execute.h */ /* execute.c -- implements execute.h */
#include "execute.h" #include "execute.h"
#define CLRMSG 0 /* space clears the message line with no insert */
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include "defines.h" #include "estruct.h"
#include "bind.h"
#include "random.h"
#include "display.h" #include "display.h"
#include "file.h" #include "file.h"
#include "input.h"
#include "mlout.h" #include "mlout.h"
#include "random.h"
#include "search.h"
#include "terminal.h"
#include "window.h" #include "window.h"
int gasave = 256 ; /* global ASAVE size */ int gasave = 256 ; /* global ASAVE size */
int gacount = 256 ; /* count until next ASAVE */ int gacount = 256 ; /* count until next ASAVE */
/* insert a # into the text here...we are in CMODE */
static int inspound( int n) {
/* if we are at the beginning of the line, no go */
if( n == 1 && curwp->w_doto != 0) {
int i ;
/* scan to see if all space before this is white space */
for( i = curwp->w_doto - 1 ; i >= 0 ; i -= 1) {
int ch ; /* last character before input */
ch = lgetc( curwp->w_dotp, i) ;
if( ch != ' ' && ch != '\t')
break ;
}
/* delete back first */
if( i < 0)
while( getccol( FALSE) >= 1)
backdel( FALSE, 1) ;
}
/* and insert the required pound */
return linsert( n, '#') ;
}
/*
* insert a brace into the text here...we are in CMODE
*
* int n; repeat count
* int c; brace to insert (if not }, just normal insertion).
*/
static int insbrace( int n, int c) {
int ch ; /* last character before input */
int oc ; /* caractere oppose a c */
int target ; /* column brace should go after */
/* if not called with {, acts as insertion */
if( c == '}')
oc = '{' ;
else
return linsert( n, c) ;
/* scan to see if all preceding spaces are white spaces, if not, insert */
for( int i = curwp->w_doto - 1 ; i >= 0 ; --i) {
ch = lgetc( curwp->w_dotp, i) ;
if( ch != ' ' && ch != '\t')
return linsert( n, c) ;
}
/* save the original cursor position */
line_p oldlp = curwp->w_dotp ;
int oldoff = curwp->w_doto ;
int count = 1 ;
do {
if( boundary( curwp->w_dotp, curwp->w_doto, REVERSE)) {
/* at beginning of buffer, no match to be found */
curwp->w_dotp = oldlp ;
curwp->w_doto = oldoff ;
return linsert( n, c) ;
}
backchar( FALSE, 1) ;
/* if not eol */
if( curwp->w_doto != llength( curwp->w_dotp)) {
ch = lgetc( curwp->w_dotp, curwp->w_doto) ;
if( ch == c)
++count ;
else if( ch == oc)
--count ;
}
} while( count > 0) ;
curwp->w_doto = 0 ; /* debut de ligne */
/* aller au debut de la ligne apres la tabulation */
while( (ch = lgetc( curwp->w_dotp, curwp->w_doto)) == ' '
|| ch == '\t')
forwchar( FALSE, 1) ;
/* delete back first */
target = getccol( FALSE) ; /* c'est l'indent que l'on doit avoir */
curwp->w_dotp = oldlp ;
curwp->w_doto = oldoff ;
while( target != getccol( FALSE)) {
if( target < getccol( FALSE)) /* on doit detruire des caracteres */
while( getccol( FALSE) > target)
backdel( FALSE, 1) ;
else { /* on doit en inserer */
while( target - getccol( FALSE) >= tabwidth)
insert_tab( FALSE, 1) ;
linsert( target - getccol( FALSE), ' ') ;
}
}
/* and insert the required brace(s) */
return linsert( n, c) ;
}
#if CFENCE
/*
* Close fences are matched against their partners, and if
* on screen the cursor briefly lights there
*
* char ch; fence type to match against
*/
static void fmatch( int ch) {
int opench ; /* open fence */
/* $tpause <= 0 disable fmatch */
if( term.t_pause <= 0)
return ;
/* first get the display update out there */
update( FALSE) ;
/* save the original cursor position */
line_p oldlp = curwp->w_dotp ;
int oldoff = curwp->w_doto ;
/* setup proper open fence for passed close fence */
if( ch == ')')
opench = '(' ;
else if( ch == '}')
opench = '{' ;
else
opench = '[' ;
/* find the top line and set up for scan */
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 */
int count = 1 ; /* current fence level count */
do {
/* At beginning of window or buffer, no match to be found */
if( curwp->w_dotp == toplp
|| boundary( curwp->w_dotp, curwp->w_doto, REVERSE))
break ;
backchar( FALSE, 1) ;
/* if not eol */
if( curwp->w_doto != llength(curwp->w_dotp)) {
int c ; /* current character in scan */
c = lgetc( curwp->w_dotp, curwp->w_doto) ;
if( c == ch)
++count ;
else if( c == opench)
--count ;
}
} while( count > 0) ;
/* if count is zero, we have a match, display the sucker */
if( count == 0) {
int i ;
/* there is a real machine dependant timing problem here we have
yet to solve......... */
for( i = 0 ; i < term.t_pause ; i++) {
update( FALSE) ;
usleep( 10000L) ;
}
}
/* restore the current position */
curwp->w_dotp = oldlp ;
curwp->w_doto = oldoff ;
}
#endif
#if CFENCE
/*
* the cursor is moved to a matching fence
*
* int f, n; not used
*/
BINDABLE( getfence) {
int sdir; /* direction of search (1/-1) */
char ch; /* fence type to match against */
char ofence; /* open fence */
char c; /* current character in scan */
/* save the original cursor position */
line_p oldlp = curwp->w_dotp ;
int oldoff = curwp->w_doto ;
/* get the current character */
if (oldoff == llength(oldlp))
ch = '\n';
else
ch = lgetc(oldlp, oldoff);
/* setup proper matching fence */
switch (ch) {
case '(':
ofence = ')';
sdir = FORWARD;
break;
case '{':
ofence = '}';
sdir = FORWARD;
break;
case '[':
ofence = ']';
sdir = FORWARD;
break;
case ')':
ofence = '(';
sdir = REVERSE;
break;
case '}':
ofence = '{';
sdir = REVERSE;
break;
case ']':
ofence = '[';
sdir = REVERSE;
break;
default:
TTbeep();
return FALSE;
}
/* scan until we find a match, or reach the end of file */
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 */
/* restore the current position */
curwp->w_dotp = oldlp ;
curwp->w_doto = oldoff ;
TTbeep() ;
return FALSE ;
}
if( sdir == FORWARD)
forwchar( FALSE, 1) ;
else
backchar( FALSE, 1) ;
/* if no eol */
if( curwp->w_doto != llength(curwp->w_dotp)) {
c = curwbyte() ;
if( c == ch)
++count ;
else if( c == ofence)
--count ;
}
} while( count > 0) ;
/* we have a match, move the sucker */
curwp->w_flag |= WFMOVE ;
return TRUE ;
}
#endif
/* /*
* This is the general command execution routine. It handles the fake binding * This is the general command execution routine. It handles the fake binding
* of all the keys to "self-insert". It also clears out the "thisflag" word, * of all the keys to "self-insert". It also clears out the "thisflag" word,
* and arranges to move it to the "lastflag", so that the next command can * and arranges to move it to the "lastflag", so that the next command can
* look at it. Return the status of command. * look at it. Return the status of command.
*/ */
int execute( unsigned c, int f, int n) { int execute(int c, int f, int n)
int status ; {
int status;
fn_t execfunc;
/* if the keystroke is a bound function...do it */ /* if the keystroke is a bound function...do it */
kbind_p ktp = getkeybinding( c) ; execfunc = getbind(c);
if( ktp->k_code != 0) { if (execfunc != NULL) {
thisflag = 0 ; thisflag = 0;
assert( ktp->k_nbp != NULL) ; status = (*execfunc) (f, n);
char tag = bind_tag( ktp->k_nbp) ; lastflag = thisflag;
if( (tag & 1) && (curbp->b_mode & MDVIEW)) return status;
status = rdonly() ;
else {
fnp_t execfunc = ktp->k_nbp->n_func ;
status = execfunc( f, n) ;
}
lastflag = thisflag ;
return status ;
} }
/* non insertable character can only be bound to function */ /*
if( c < 0x20 * If a space was typed, fill column is defined, the argument is non-
|| (c >= 0x7F && c < 0xA0) * negative, wrap mode is enabled, and we are now past fill column,
|| c > 0x10FFFF) { /* last valid unicode */ * and we are not read-only, perform word wrap.
lastflag = 0 ; /* Fake last flags. */ */
mloutfmt( "%B(Key not bound)") ; /* Complain */ if (c == ' ' && (curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
return FALSE ; n >= 0 && getccol(FALSE) > fillcol &&
} (curwp->w_bufp->b_mode & MDVIEW) == FALSE)
execute(META | SPEC | 'W', FALSE, 1);
/* insertable character => self insert, check if buffer is read only */ #if PKCODE
if( curbp->b_mode & MDVIEW) { if ((c >= 0x20 && c <= 0x7E) /* Self inserting. */
lastflag = 0 ; #if IBMPC
return rdonly() ; || (c >= 0x80 && c <= 0xFE)) {
}
/* check valid count */
if( n <= 0) {
lastflag = 0 ;
return n < 0 ? FALSE : TRUE ;
}
/* wrap on space after fill column in wrap mode */
if( c == ' '
&& (curwp->w_bufp->b_mode & MDWRAP)
&& fillcol > 0
&& getccol( FALSE) > fillcol) {
status = execute( META | SPEC | 'W', FALSE, 1) ; /* defaults to wrapword */
if( status != TRUE) {
lastflag = 0 ;
return status ;
}
}
thisflag = 0 ; /* For the future. */
/* following handling of overwrite is only valid when n == 1 */
/* if we are in overwrite mode, not at eol,
and next char is not a tab or we are at a tab stop,
delete a char forward */
if( curbp->b_mode & MDOVER
&& curwp->w_doto < curwp->w_dotp->l_used
&& (lgetc( curwp->w_dotp, curwp->w_doto) != '\t' ||
((curwp->w_doto) % tabwidth) == (tabwidth - 1)))
ldelchar( 1, FALSE) ;
/* do the appropriate insertion */
switch( c) {
case '}':
case ']':
case ')':
case '#':
if( (curbp->b_mode & MDCMOD) != 0) {
if( c == '#')
status = inspound( n) ;
else {
status = insbrace( n, c) ;
#if CFENCE
if( status == TRUE)
fmatch( c) ; /* check for CMODE fence matching */
#endif
}
break ;
}
/* fallthrough */
default:
status = linsert( n, c) ;
}
/* perform auto-save */
if( status == TRUE /* successful insertion */
&& (curbp->b_mode & MDASAVE) /* auto save is on */
&& (--gacount == 0)) { /* insertion count reached */
/* and save the file if needed */
upscreen( FALSE, 0) ;
filesave( FALSE, 0) ;
gacount = gasave ;
}
lastflag = thisflag ;
return status ;
}
void kbd_loop( void) {
int c = -1 ; /* command character */
/* Setup to process commands. */
lastflag = 0 ; /* Fake last flags. */
for( ;;) {
int saveflag ; /* temp store for lastflag */
int basec ; /* c stripped of meta character */
int f ; /* default flag */
int n ; /* numeric repeat count */
/* Execute the "command" macro...normally null. */
saveflag = lastflag ; /* Preserve lastflag through this. */
execute( META | SPEC | 'C', FALSE, 1) ;
lastflag = saveflag ;
#if TYPEAH && PKCODE
if( typahead()) {
int newc ;
newc = getcmd() ;
update( FALSE) ;
do {
kbind_p ktp ;
fnp_t execfunc ;
if( c == newc
&& (ktp = getkeybinding( c))->k_code == c
&& (execfunc = ktp->k_nbp->k_func) != insert_newline
&& execfunc != insert_tab)
newc = getcmd() ;
else
break ;
} while( typahead()) ;
c = newc ;
} else {
update( FALSE) ;
c = getcmd() ;
}
#else #else
/* Fix up the screen */ #if VMS || BSD || USG /* 8BIT P.K. */
update( FALSE) ; || (c >= 0xA0 && c <= 0x10FFFF)) {
#else
/* get the next command from the keyboard */ ) {
c = getcmd() ;
#endif #endif
/* if there is something on the command line, clear it */
if( mpresf != FALSE) {
mloutstr( "") ;
update( FALSE) ;
#if CLRMSG
if( c == ' ') /* ITS EMACS does this */
continue ;
#endif #endif
} #else
if ((c >= 0x20 && c <= 0xFF)) { /* Self inserting. */
f = FALSE ; #endif
n = 1 ; if (n <= 0) { /* Fenceposts. */
lastflag = 0;
/* do META-# processing if needed */ return n < 0 ? FALSE : TRUE;
/* do ^U repeat argument processing */
while( c == reptc
||( (c & META)
&& (((basec = c & ~META) >= '0' && basec <= '9') || basec == '-'))) {
int mflag = 0 ; /* minus flag, default to positive */
f = TRUE ;
if( c == reptc) {
n = 4 ;
basec = 2 ; /* lead by universal arg cmd */
} else if( c & META) {
if( basec == '-') {
mflag = TRUE ; /* negative */
n = 1 ;
basec = 1 ; /* lead by M-- */
} else {
n = basec - '0' ;
basec = 0 ; /* lead by M-# */
}
} }
thisflag = 0; /* For the future. */
mloutfmt( "Arg: %s%d", mflag ? "-" : "", n) ; /* if we are in overwrite mode, not at eol,
while( ((c = getcmd()) >= '0' && c <= '9') || c == '-') { and next char is not a tab or we are at a tab stop,
if( c == '-') { delete a char forword */
if( basec == 2) { /* directly follows universal arg cmd */ if (curwp->w_bufp->b_mode & MDOVER &&
n = 1 ; curwp->w_doto < curwp->w_dotp->l_used &&
basec = 1 ; (lgetc(curwp->w_dotp, curwp->w_doto) != '\t' ||
mflag = TRUE ; (curwp->w_doto) % 8 == 7))
} else ldelchar(1, FALSE);
break ;
} else { /* do the appropriate insertion */
if( basec) { /* follows universal arg cmd or leading dash */ if (c == '}' && (curbp->b_mode & MDCMOD) != 0)
n = c - '0' ; status = insbrace(n, c);
basec = 0 ; else if (c == '#' && (curbp->b_mode & MDCMOD) != 0)
} else if( n <= 0xCCCCCCB) /* avoid overflow */ status = inspound();
n = n * 10 + c - '0' ; else
status = linsert(n, c);
#if CFENCE
/* check for CMODE fence matching */
if ((c == '}' || c == ')' || c == ']') &&
(curbp->b_mode & MDCMOD) != 0)
fmatch(c);
#endif
/* check auto-save mode */
if (curbp->b_mode & MDASAVE)
if (--gacount == 0) {
/* and save the file if needed */
upscreen(FALSE, 0);
filesave(FALSE, 0);
gacount = gasave;
} }
mloutfmt( "Arg: %s%d", mflag ? "-" : "", n) ; lastflag = thisflag;
} return status;
if( mflag)
n = -n ;
} }
/* and execute the command */ lastflag = 0 ; /* Fake last flags. */
execute( c, f, n) ; mloutfmt( "%B(Key not bound)") ; /* Complain */
} return FALSE ;
} }
/* end of execute.c */

View File

@ -1,19 +1,5 @@
/* execute.h -- */ extern int gasave ; /* global ASAVE size */
#ifndef _EXECUTE_H_ extern int gacount ; /* count until next ASAVE */
#define _EXECUTE_H_
#include "names.h" /* BINDABLE() */ int execute( int c, int f, int n) ;
extern int gasave ; /* global ASAVE size */
extern int gacount ; /* count until next ASAVE */
int execute( unsigned keycode, int f, int n) ;
void kbd_loop( void) ;
#define CFENCE 1 /* fence matching in CMODE */
#if CFENCE
BINDABLE( getfence) ;
#endif
#endif
/* end of execute.h */

944
file.c

File diff suppressed because it is too large Load Diff

30
file.h
View File

@ -1,27 +1,29 @@
/* file.h -- file centric commands */
#ifndef _FILE_H_ #ifndef _FILE_H_
#define _FILE_H_ #define _FILE_H_
#include "buffer.h" /* bname_t */ #include "buffer.h"
#include "names.h" /* BINDABLE() */ #include "crypt.h"
#include "retcode.h"
extern boolean restflag ; /* restricted use? */ #if CRYPT
boolean resterr( void) ; /* restricted error message */ void cryptbufferkey( struct buffer *bp) ;
int set_encryption_key( int f, int n) ;
#endif
/* Bindable functions */ extern boolean restflag ; /* restricted use? */
BINDABLE( filefind) ; boolean resterr( void) ; /* restricted error message */
BINDABLE( fileread) ;
BINDABLE( filename) ;
BINDABLE( filesave) ;
BINDABLE( filewrite) ;
BINDABLE( insfile) ;
BINDABLE( viewfile) ;
int fileread( int f, int n) ;
int insfile( int f, int n) ;
int filefind( int f, int n) ;
int viewfile( int f, int n) ;
int getfile( const char *fname, boolean lockfl) ; int getfile( const char *fname, boolean lockfl) ;
int readin( const char *fname, boolean lockfl) ; int readin( const char *fname, boolean lockfl) ;
void makename( bname_t bname, const char *fname) ; void makename( bname_t bname, const char *fname) ;
void unqname( char *name) ; void unqname( char *name) ;
int filewrite( int f, int n) ;
int filesave( int f, int n) ;
int writeout( const char *fn) ; int writeout( const char *fn) ;
int filename( int f, int n) ;
#endif #endif
/* end of file.h */

251
fileio.c
View File

@ -1,10 +1,18 @@
/* fileio.c -- implements fileio.h */ /* fileio.c -- implements fileio.h */
#include "fileio.h" #include "fileio.h"
/* The routines in this file read and write ASCII files from the disk. All #ifdef CTRLZ
of the knowledge about files are here. #undef CTRLZ
#endif
#define CTRLZ 0 /* add a ^Z at end of files under MSDOS only */
modified by Petri Kutvonen /* FILEIO.C
*
* The routines in this file read and write ASCII files from the disk. All of
* the knowledge about files are here.
*
* modified by Petri Kutvonen
*/ */
#include <stdio.h> #include <stdio.h>
@ -15,62 +23,104 @@
#include "retcode.h" #include "retcode.h"
#include "utf8.h" #include "utf8.h"
char *fline = NULL ; /* dynamic return line */ #if CRYPT
static int flen = 0 ; /* current allocated length of fline */ boolean is_crypted ; /* currently encrypting? */
int ftype ; #endif
int fcode ; /* encoding type FCODE_xxxxx */
int fpayload ; /* actual length of fline content */ char *fline = NULL ; /* dynamic return line */
static int flen = 0 ; /* current allocated length of fline */
int ftype ;
int fcode ; /* encoding type FCODE_xxxxx */
int fpayload ; /* actual length of fline content */
static FILE *ffp ; /* File pointer, all functions. */ static FILE *ffp ; /* File pointer, all functions. */
static boolean eofflag ; /* end-of-file flag */ static boolean eofflag ; /* end-of-file flag */
/* Open a file for reading. */ /*
fio_code ffropen( const char *fn) { * Open a file for reading.
eofflag = FALSE ; */
fio_code ffropen( const char *fn)
{
if ((ffp = fopen(fn, "r")) == NULL)
return FIOFNF;
eofflag = FALSE;
ftype = FTYPE_NONE ; ftype = FTYPE_NONE ;
fcode = FCODE_ASCII ; fcode = FCODE_ASCII ;
ffp = fopen( fn, "r") ; return FIOSUC;
return (ffp == NULL) ? FIOFNF : FIOSUC ;
} }
/*
/* Open a file for writing. Return TRUE if all is well, and FALSE on error * Open a file for writing. Return TRUE if all is well, and FALSE on error
(cannot create). * (cannot create).
*/ */
fio_code ffwopen( const char *fn) { fio_code ffwopen( const char *fn)
ffp = fopen( fn, "w") ; {
return (ffp == NULL) ? FIOERR : FIOSUC ; #if VMS
int fd;
if ((fd = creat(fn, 0666, "rfm=var", "rat=cr")) < 0
|| (ffp = fdopen(fd, "w")) == NULL)
#else
if ((ffp = fopen(fn, "w")) == NULL)
#endif
return FIOERR;
return FIOSUC;
} }
/*
/* Close a file. Should look at the status in all systems. * Close a file. Should look at the status in all systems.
*/ */
fio_code ffclose( void) { fio_code ffclose(void)
{
/* free this since we do not need it anymore */ /* free this since we do not need it anymore */
if( fline) { if (fline) {
free( fline) ; free(fline);
fline = NULL ; fline = NULL;
} }
eofflag = FALSE;
eofflag = FALSE ;
ftype = FTYPE_NONE ; ftype = FTYPE_NONE ;
fcode = FCODE_ASCII ; fcode = FCODE_ASCII ;
return (fclose( ffp) != FALSE) ? FIOERR : FIOSUC ; #if MSDOS & CTRLZ
fputc(26, ffp); /* add a ^Z at the end of the file */
#endif
#if V7 | USG | BSD | (MSDOS & (MSC | TURBO))
if (fclose(ffp) != FALSE)
return FIOERR;
#else
fclose(ffp);
#endif
return FIOSUC;
} }
/*
/* Write a line to the already opened file. The "buf" points to the * Write a line to the already opened file. The "buf" points to the buffer,
buffer, and the "nbuf" is its length, less the free newline. Return the * and the "nbuf" is its length, less the free newline. Return the status.
status. Check only at the newline. * Check only at the newline.
*/ */
fio_code ffputline( char *buf, int nbuf, int dosflag) { fio_code ffputline( char *buf, int nbuf, int dosflag) {
fwrite( buf, 1, nbuf, ffp) ; #if CRYPT
if( is_crypted) {
int i ;
if( dosflag) for( i = 0 ; i < nbuf ; i++) {
fputc( '\r', ffp) ; char c ;
c = buf[ i] ;
myencrypt( &c, 1) ;
fputc( c, ffp) ;
}
} else
#endif
fwrite( buf, 1, nbuf, ffp) ;
if( dosflag)
fputc( '\r', ffp) ;
fputc( '\n', ffp) ; fputc( '\n', ffp) ;
@ -80,91 +130,98 @@ fio_code ffputline( char *buf, int nbuf, int dosflag) {
return FIOSUC ; return FIOSUC ;
} }
/* Read a line from a file, and store the bytes in the supplied buffer. /*
The "nbuf" is the length of the buffer. Complain about long lines and * Read a line from a file, and store the bytes in the supplied buffer. The
lines at the end of the file that don't have a newline present. Check * "nbuf" is the length of the buffer. Complain about long lines and lines
for I/O errors too. Return status. * at the end of the file that don't have a newline present. Check for I/O
* errors too. Return status.
*/ */
fio_code ffgetline( void) { fio_code ffgetline(void)
int c ; /* current character read */ {
int lcode = FCODE_ASCII ; /* line encoding, defaults to ASCII */ int c; /* current character read */
int i; /* current index into fline */
int lcode = FCODE_ASCII ; /* line encoding, defaults to ASCII */
/* if we are at the end...return it */ /* if we are at the end...return it */
if( eofflag) if (eofflag)
return FIOEOF ; return FIOEOF;
/* dump fline if it ended up too big */ /* dump fline if it ended up too big */
if( flen > NSTRING) { if (flen > NSTRING) {
free( fline) ; free(fline);
fline = NULL ; fline = NULL;
} }
/* if we don't have an fline, allocate one */ /* if we don't have an fline, allocate one */
if( fline == NULL) if (fline == NULL)
if( (fline = malloc( flen = NSTRING)) == NULL) if ((fline = malloc(flen = NSTRING)) == NULL)
return FIOMEM ; return FIOMEM;
/* read the line in */ /* read the line in */
int i = 0 ; /* current index into fline */ i = 0;
while( (c = fgetc( ffp)) != EOF && c != '\r' && c != '\n') { while ((c = fgetc(ffp)) != EOF && c != '\r' && c != '\n') {
/* if line is full, get more room */ fline[i++] = c;
if( i >= flen) { lcode |= c ;
char *tmpline ; /* temp storage for expanding line */ /* if it's longer, get more room */
if (i >= flen) {
tmpline = malloc( flen + NSTRING) ; char *tmpline; /* temp storage for expanding line */
fpayload = i ;
tmpline = malloc(flen + NSTRING) ;
if( tmpline == NULL) if( tmpline == NULL)
return FIOMEM ; return FIOMEM ;
memcpy( tmpline, fline, flen) ; memcpy( tmpline, fline, flen) ;
flen += NSTRING ; flen += NSTRING;
free( fline) ; free(fline);
fline = tmpline ; fline = tmpline;
} }
fline[ i++] = c ;
lcode |= c ;
} }
fpayload = i ; fpayload = i ;
if( lcode & 0x80 /* line contains extended chars */ lcode &= FCODE_MASK ;
&& (fcode != FCODE_MIXED)) { if( lcode && (fcode != FCODE_MIXED)) { /* line contains extended chars */
/* Check if consistent UTF-8 encoding */ /* Check if consistent UTF-8 encoding */
lcode = FCODE_ASCII ; int bytes ;
int pos = 0 ; int pos = 0 ;
while( (pos < i) && (lcode != FCODE_MIXED)) { unicode_t uc ;
unicode_t uc ;
int bytes = utf8_to_unicode( fline, pos, i, &uc) ; while( (pos < i) && (lcode != FCODE_MIXED)) {
pos += bytes ; bytes = utf8_to_unicode( fline, pos, i, &uc) ;
if( bytes > 1) /* Multi byte UTF-8 sequence */ pos += bytes ;
lcode |= FCODE_UTF_8 ; if( bytes > 1) /* Multi byte UTF-8 sequence */
else if( uc > 127) /* Extended ASCII */ lcode |= FCODE_UTF_8 ;
lcode |= FCODE_EXTND ; else if( uc > 127) /* Extended ASCII */
} lcode |= FCODE_EXTND ;
}
fcode |= lcode ; fcode |= lcode ;
} }
/* test for any errors that may have occured */ /* test for any errors that may have occured */
if( c == EOF) { if (c == EOF) {
if( ferror( ffp)) if( ferror( ffp))
return FIOERR ; return FIOERR ;
if( i != 0) if (i != 0)
eofflag = TRUE ; eofflag = TRUE;
else else
return FIOEOF ; return FIOEOF;
} else if( c == '\r') { } else if( c == '\r') {
c = fgetc( ffp) ; c = fgetc( ffp) ;
if( c != '\n') { if( c != '\n') {
ftype |= FTYPE_MAC ; ftype |= FTYPE_MAC ;
ungetc( c, ffp) ; ungetc( c, ffp) ;
} else } else
ftype |= FTYPE_DOS ; ftype |= FTYPE_DOS ;
} else /* c == '\n' */ } else /* c == '\n' */
ftype |= FTYPE_UNIX ; ftype |= FTYPE_UNIX ;
return FIOSUC ; /* terminate and decrypt the string */
fline[i] = 0;
#if CRYPT
if( is_crypted)
myencrypt( fline, fpayload);
#endif
return FIOSUC;
} }
/* end of fileio.c */

View File

@ -1,13 +1,15 @@
/* fileio.h -- file primitives */
#ifndef _FILEIO_H_ #ifndef _FILEIO_H_
#define _FILEIO_H_ #define _FILEIO_H_
#include "crypt.h"
typedef enum { typedef enum {
FIOSUC, /* File I/O, success. */ FIOSUC, /* File I/O, success. */
FIOFNF, /* File I/O, file not found. */ FIOFNF, /* File I/O, file not found. */
FIOEOF, /* File I/O, end of file. */ FIOEOF, /* File I/O, end of file. */
FIOERR, /* File I/O, error. */ FIOERR, /* File I/O, error. */
FIOMEM /* File I/O, out of memory */ FIOMEM, /* File I/O, out of memory */
FIOFUN /* File I/O, eod of file/bad line */
} fio_code ; } fio_code ;
#define FTYPE_NONE 0 #define FTYPE_NONE 0
@ -17,14 +19,21 @@ typedef enum {
/* FTYPE_MIXED [ 3, 5, 6, 7] */ /* FTYPE_MIXED [ 3, 5, 6, 7] */
#define FCODE_ASCII 0 #define FCODE_ASCII 0
#define FCODE_UTF_8 1 #define FCODE_MASK 0x80
#define FCODE_EXTND 2 #define FCODE_UTF_8 0x81
#define FCODE_MIXED 3 #define FCODE_EXTND 0x82
#define FCODE_MIXED 0x83
extern char *fline ; /* dynamic return line */ #if CRYPT
extern int ftype ; #include "retcode.h"
extern int fcode ; /* encoding type */
extern int fpayload ; /* actual length of fline content */ extern boolean is_crypted ; /* currently encrypting? */
#endif
extern char *fline ; /* dynamic return line */
extern int ftype ;
extern int fcode ; /* encoding type */
extern int fpayload ; /* actual length of fline content */
fio_code ffclose( void) ; fio_code ffclose( void) ;
fio_code ffgetline( void) ; fio_code ffgetline( void) ;
@ -33,4 +42,3 @@ fio_code ffropen( const char *fn) ;
fio_code ffwopen( const char *fn) ; fio_code ffwopen( const char *fn) ;
#endif #endif
/* end of fileio.h */

View File

@ -1,67 +0,0 @@
## floodmaz.cmd -- solve maze by painting wall on the right
# 6 set $seed
# either maze.cmd or sharpmaz.cmd
execute-file sharpmaz.cmd
set %thisbuf $cbufname
set %meml $curline
set %memc $curcol
set $curline 1
set $curcol 0
!gosub pushxy #push stop position
set %x 1
set $curline 4
set $curcol %x
set %OC $curchar
set %NC &asc ""
!while &not &equ %x 0
set $curchar %NC
set %cc $curcol
set %ll $curline
set $curcol &add %cc 1
!gosub probe
set $curcol &add %cc -1
!gosub probe
set $curline &add %ll 1
set $curcol %cc
!gosub probe
set $curline &add %ll -1
set $curcol %cc
!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 %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

235
flook.c
View File

@ -1,131 +1,172 @@
/* flook.c -- implements flook.h */ /* flook.c -- implements flook.h */
#include "flook.h" #include "flook.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "defines.h" #include "defines.h"
#include "fileio.h"
/* possible names and paths of help files under different OSes */ /* possible names and paths of help files under different OSs */
const char *pathname[] = { const char *pathname[] = {
#if BSD | USG #if MSDOS
".emacsrc", "emacs.rc",
"emacs.hlp", "emacs.hlp",
# if PKCODE "\\sys\\public\\",
"/usr/global/lib/", "/usr/local/bin/", "/usr/local/lib/", "\\usr\\bin\\",
# endif "\\bin\\",
"/usr/local/", "/usr/lib/", "" "\\",
""
#endif #endif
} ;
#define PATHTABLE_SIZE (sizeof pathname / sizeof pathname[ 0]) #if V7 | BSD | USG
".emacsrc",
"emacs.hlp",
#if PKCODE
"/usr/global/lib/", "/usr/local/bin/", "/usr/local/lib/",
#endif
"/usr/local/", "/usr/lib/", ""
#endif
#if VMS
{
"emacs.rc", "emacs.hlp", "",
#if PKCODE
"sys$login:", "emacs_dir:",
#endif
"sys$sysdevice:[vmstools]"
#endif
};
#define PATHNAME_SIZE (sizeof pathname / sizeof pathname[ 0])
/* does <fname> exist on disk? /*
* does <fname> exist on disk?
* *
* char *fname; file to check for existance * char *fname; file to check for existance
*/ */
boolean fexist( const char *fname) { boolean fexist( const char *fname)
FILE *fp = fopen( fname, "r") ; {
if( fp == NULL) FILE *fp;
return FALSE ;
else
fclose( fp) ;
return TRUE ; /* try to open the file for reading */
fp = fopen(fname, "r");
/* if it fails, just return false! */
if (fp == NULL)
return FALSE;
/* otherwise, close it and report true */
fclose(fp);
return TRUE;
} }
/*
/* Look up the existence of a file along the normal or PATH environment * Look up the existance of a file along the normal or PATH
variable. Look first in the HOME directory if asked and possible. * environment variable. Look first in the HOME directory if
* asked and possible
char *fname; base file name to search for *
boolean hflag; look in the HOME environment variable first? * char *fname; base file name to search for
* boolean hflag; Look in the HOME environment variable first?
*/ */
char *flook( const char *fname, boolean hflag) { char *flook( const char *fname, boolean hflag)
static char fspec[ NSTRING] ; /* full path spec to search */ {
unsigned i ; /* index */
int len ;
static char fspec[NSTRING]; /* full path spec to search */
int len = sizeof fspec - strlen( fname) - 1 ; #if ENVFUNC
if( len < 0) char *path; /* environmental PATH variable */
return NULL ;
#if ENVFUNC
if( hflag) {
char *home = getenv( "HOME") ; /* path to home directory */
if( home != NULL) {
if( len > (int) strlen( home) + 1) {
/* build home dir file spec */
strcpy( fspec, home) ;
strcat( fspec, "/") ;
strcat( fspec, fname) ;
/* and try it out */
if( fexist( fspec))
return fspec ;
}
}
}
#endif #endif
/* always try the current directory first */ len = sizeof fspec - strlen( fname) - 1 ;
if( len >= 0) { if( len < 0)
strcpy( fspec, fname) ; return NULL ;
if( fexist( fspec))
return fspec ;
}
#if ENVFUNC #if ENVFUNC
# if USG | BSD if (hflag) {
# define PATHCHR ':' char *home; /* path to home directory */
# else
# define PATHCHR ';'
# endif
/* get the PATH variable */ home = getenv("HOME");
char *path = getenv( "PATH") ; /* environmental PATH variable */ if (home != NULL) {
if( path != NULL) if( len > (int) strlen( home) + 1) {
while( *path) { /* build home dir file spec */
int cnt = len ; strcpy( fspec, home) ;
/* build next possible file spec */ strcat(fspec, "/");
char *sp = fspec ; /* pointer into path spec */ strcat(fspec, fname);
while( *path && (*path != PATHCHR)) {
if( cnt-- > 0)
*sp++ = *path ;
path += 1 ; /* and try it out */
} if( fexist( fspec))
return fspec ;
if( cnt >= 0) { }
/* add a terminating dir separator if we need it */ }
if (sp != fspec) }
*sp++ = '/';
*sp = 0;
strcat(fspec, fname);
/* and try it out */
if( fexist( fspec))
return fspec ;
}
if( *path == PATHCHR)
++path ;
}
#endif #endif
/* look it up via the old table method */ /* always try the current directory first */
for( unsigned i = 2 ; i < PATHTABLE_SIZE ; i++) if( len >= 0) {
if( len >= (int) strlen( pathname[ i])) { strcpy( fspec, fname) ;
strcpy( fspec, pathname[ i]) ; if( fexist( fspec))
strcat( fspec, fname); return fspec ;
}
/* and try it out */ #if ENVFUNC
if( fexist( fspec)) #if V7 | USG | BSD
return fspec ; #define PATHCHR ':'
} #else
#define PATHCHR ';'
#endif
return NULL ; /* no such luck */ /* get the PATH variable */
path = getenv("PATH");
if (path != NULL)
while (*path) {
char *sp; /* pointer into path spec */
int cnt ;
cnt = len ;
/* build next possible file spec */
sp = fspec;
while( *path && (*path != PATHCHR)) {
if( cnt-- > 0)
*sp++ = *path ;
path += 1 ;
}
if( cnt >= 0) {
/* add a terminating dir separator if we need it */
if (sp != fspec)
*sp++ = '/';
*sp = 0;
strcat(fspec, fname);
/* and try it out */
if( fexist( fspec))
return fspec ;
}
if (*path == PATHCHR)
++path;
}
#endif
/* look it up via the old table method */
for( i = 2; i < PATHNAME_SIZE ; i++)
if( len >= (int) strlen( pathname[ i])) {
strcpy( fspec, pathname[ i]) ;
strcat( fspec, fname);
/* and try it out */
if( fexist( fspec))
return fspec ;
}
return NULL; /* no such luck */
} }
/* end of flook.c */

11
flook.h
View File

@ -1,11 +1,8 @@
/* flook.h -- */ #include "retcode.h"
#ifndef _FLOOK_H_
#define _FLOOK_H_
#include "retcode.h" /* boolean */
#define rcfname pathname[ 0] #define rcfname pathname[ 0]
#define hlpfname pathname[ 1] #define hlpfname pathname[ 1]
extern const char *pathname[] ; extern const char *pathname[] ;
@ -13,5 +10,3 @@ extern const char *pathname[] ;
boolean fexist( const char *fname) ; boolean fexist( const char *fname) ;
char *flook( const char *fname, boolean hflag) ; char *flook( const char *fname, boolean hflag) ;
#endif
/* end of flook.h */

241
fridge/ansi.c Normal file
View File

@ -0,0 +1,241 @@
/* ANSI.C
*
* The routines in this file provide support for ANSI style terminals
* over a serial line. The serial I/O services are provided by routines in
* "termio.c". It compiles into nothing if not an ANSI device.
*
* modified by Petri Kutvonen
*/
#define termdef 1 /* don't define "term" external */
#include <stdio.h>
#include "estruct.h"
#if ANSI
#define NROW 25 /* Screen size. */
#define NCOL 80 /* Edit if you want to. */
#if PKCODE
#define MROW 64
#endif
#define NPAUSE 100 /* # times thru update to pause */
#define MARGIN 8 /* size of minimim margin and */
#define SCRSIZ 64 /* scroll size for extended lines */
#define BEL 0x07 /* BEL character. */
#define ESC 0x1B /* ESC character. */
extern int ttopen(); /* Forward references. */
extern int ttgetc();
extern int ttputc();
extern int ttflush();
extern int ttclose();
extern int ansimove();
extern int ansieeol();
extern int ansieeop();
extern int ansibeep();
extern int ansiopen();
extern int ansirev();
extern int ansiclose();
extern int ansikopen();
extern int ansikclose();
extern int ansicres();
#if COLOR
extern int ansifcol();
extern int ansibcol();
int cfcolor = -1; /* current forground color */
int cbcolor = -1; /* current background color */
#endif
/*
* Standard terminal interface dispatch table. Most of the fields point into
* "termio" code.
*/
struct terminal term = {
#if PKCODE
MROW - 1,
#else
NROW - 1,
#endif
NROW - 1,
NCOL,
NCOL,
MARGIN,
SCRSIZ,
NPAUSE,
ansiopen,
ansiclose,
ansikopen,
ansikclose,
ttgetc,
ttputc,
ttflush,
ansimove,
ansieeol,
ansieeop,
ansibeep,
ansirev,
ansicres
#if COLOR
, ansifcol,
ansibcol
#endif
#if SCROLLCODE
, NULL
#endif
};
#if COLOR
ansifcol(color)
/* set the current output color */
int color; /* color to set */
{
if (color == cfcolor)
return;
ttputc(ESC);
ttputc('[');
ansiparm(color + 30);
ttputc('m');
cfcolor = color;
}
/* Set the current background color.
* color: color to set.
*/
void ansibcol(int color)
{
if (color == cbcolor)
return;
ttputc(ESC);
ttputc('[');
ansiparm(color + 40);
ttputc('m');
cbcolor = color;
}
#endif
ansimove(row, col)
{
ttputc(ESC);
ttputc('[');
ansiparm(row + 1);
ttputc(';');
ansiparm(col + 1);
ttputc('H');
}
void ansieeol(void)
{
ttputc(ESC);
ttputc('[');
ttputc('K');
}
void ansieeop(void)
{
#if COLOR
ansifcol(gfcolor);
ansibcol(gbcolor);
#endif
ttputc(ESC);
ttputc('[');
ttputc('J');
}
/* Change reverse video state.
* state: TRUE = reverse, FALSE = normal
*/
void ansirev(int state)
{
#if COLOR
int ftmp, btmp; /* temporaries for colors */
#endif
ttputc(ESC);
ttputc('[');
ttputc(state ? '7' : '0');
ttputc('m');
#if COLOR
if (state == FALSE) {
ftmp = cfcolor;
btmp = cbcolor;
cfcolor = -1;
cbcolor = -1;
ansifcol(ftmp);
ansibcol(btmp);
}
#endif
}
/* Change screen resolution. */
int ansicres()
{
return TRUE;
}
void ansibeep(void)
{
ttputc(BEL);
ttflush();
}
void ansiparm(int n)
{
int q, r;
q = n / 10;
if (q != 0) {
r = q / 10;
if (r != 0) {
ttputc((r % 10) + '0');
}
ttputc((q % 10) + '0');
}
ttputc((n % 10) + '0');
}
void ansiopen(void)
{
#if V7 | USG | BSD
char *cp;
if ((cp = getenv("TERM")) == NULL) {
puts("Shell variable TERM not defined!");
exit(1);
}
if (strcmp(cp, "vt100") != 0) {
puts("Terminal type not 'vt100'!");
exit(1);
}
#endif
strcpy(sres, "NORMAL");
revexist = TRUE;
ttopen();
}
void ansiclose(void)
{
#if COLOR
ansifcol(7);
ansibcol(0);
#endif
ttclose();
}
/* Open the keyboard (a noop here). */
void ansikopen(void)
{
}
/* Close the keyboard (a noop here). */
void ansikclose(void)
{
}
#endif

494
fridge/ibmpc.c Normal file
View File

@ -0,0 +1,494 @@
/* ibmpc.c
*
* The routines in this file provide support for the IBM-PC and other
* compatible terminals. It goes directly to the graphics RAM to do
* screen output. It compiles into nothing if not an IBM-PC driver
* Supported monitor cards include CGA, MONO and EGA.
*
* modified by Petri Kutvonen
*/
#define termdef 1 /* don't define "term" external */
#include <stdio.h>
#include "estruct.h"
#if IBMPC
#if PKCODE
#define NROW 50
#else
#define NROW 43 /* Max Screen size. */
#endif
#define NCOL 80 /* Edit if you want to. */
#define MARGIN 8 /* size of minimim margin and */
#define SCRSIZ 64 /* scroll size for extended lines */
#define NPAUSE 200 /* # times thru update to pause */
#define BEL 0x07 /* BEL character. */
#define ESC 0x1B /* ESC character. */
#define SPACE 32 /* space character */
#define SCADC 0xb8000000L /* CGA address of screen RAM */
#define SCADM 0xb0000000L /* MONO address of screen RAM */
#define SCADE 0xb8000000L /* EGA address of screen RAM */
#define MONOCRSR 0x0B0D /* monochrome cursor */
#define CGACRSR 0x0607 /* CGA cursor */
#define EGACRSR 0x0709 /* EGA cursor */
#define CDCGA 0 /* color graphics card */
#define CDMONO 1 /* monochrome text card */
#define CDEGA 2 /* EGA color adapter */
#if PKCODE
#define CDVGA 3
#endif
#define CDSENSE 9 /* detect the card type */
#if PKCODE
#define NDRIVE 4
#else
#define NDRIVE 3 /* number of screen drivers */
#endif
int dtype = -1; /* current display type */
char drvname[][8] = { /* screen resolution names */
"CGA", "MONO", "EGA"
#if PKCODE
, "VGA"
#endif
};
long scadd; /* address of screen ram */
int *scptr[NROW]; /* pointer to screen lines */
unsigned int sline[NCOL]; /* screen line image */
int egaexist = FALSE; /* is an EGA card available? */
extern union REGS rg; /* cpu register for use of DOS calls */
extern int ttopen(); /* Forward references. */
extern int ttgetc();
extern int ttputc();
extern int ttflush();
extern int ttclose();
extern int ibmmove();
extern int ibmeeol();
extern int ibmeeop();
extern int ibmbeep();
extern int ibmopen();
extern int ibmrev();
extern int ibmcres();
extern int ibmclose();
extern int ibmputc();
extern int ibmkopen();
extern int ibmkclose();
#if COLOR
extern int ibmfcol();
extern int ibmbcol();
extern int ibmscroll_reg();
int cfcolor = -1; /* current forground color */
int cbcolor = -1; /* current background color */
int ctrans[] = /* ansi to ibm color translation table */
#if PKCODE
{ 0, 4, 2, 6, 1, 5, 3, 7, 15 };
#else
{ 0, 4, 2, 6, 1, 5, 3, 7 };
#endif
#endif
/*
* Standard terminal interface dispatch table. Most of the fields point into
* "termio" code.
*/
struct terminal term = {
NROW - 1,
NROW - 1,
NCOL,
NCOL,
MARGIN,
SCRSIZ,
NPAUSE,
ibmopen,
ibmclose,
ibmkopen,
ibmkclose,
ttgetc,
ibmputc,
ttflush,
ibmmove,
ibmeeol,
ibmeeop,
ibmbeep,
ibmrev,
ibmcres
#if COLOR
, ibmfcol,
ibmbcol
#endif
#if SCROLLCODE
, ibmscroll_reg
#endif
};
#if COLOR
/* Set the current output color.
*
* @color: color to set.
*/
void ibmfcol(int color)
{
cfcolor = ctrans[color];
}
/* Set the current background color.
*
* @color: color to set.
*/
void ibmbcol(int color)
{
cbcolor = ctrans[color];
}
#endif
void ibmmove(int row, int col)
{
rg.h.ah = 2; /* set cursor position function code */
rg.h.dl = col;
rg.h.dh = row;
rg.h.bh = 0; /* set screen page number */
int86(0x10, &rg, &rg);
}
void ibmeeol(void)
{ /* erase to the end of the line */
unsigned int attr; /* attribute byte mask to place in RAM */
unsigned int *lnptr; /* pointer to the destination line */
int i;
int ccol; /* current column cursor lives */
int crow; /* row */
/* find the current cursor position */
rg.h.ah = 3; /* read cursor position function code */
rg.h.bh = 0; /* current video page */
int86(0x10, &rg, &rg);
ccol = rg.h.dl; /* record current column */
crow = rg.h.dh; /* and row */
/* build the attribute byte and setup the screen pointer */
#if COLOR
if (dtype != CDMONO)
attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8;
else
attr = 0x0700;
#else
attr = 0x0700;
#endif
lnptr = &sline[0];
for (i = 0; i < term.t_ncol; i++)
*lnptr++ = SPACE | attr;
if (flickcode && (dtype == CDCGA)) {
/* wait for vertical retrace to be off */
while ((inp(0x3da) & 8));
/* and to be back on */
while ((inp(0x3da) & 8) == 0);
}
/* and send the string out */
movmem(&sline[0], scptr[crow] + ccol, (term.t_ncol - ccol) * 2);
}
/* Put a character at the current position in the current colors */
void ibmputc(int ch)
{
rg.h.ah = 14; /* write char to screen with current attrs */
rg.h.al = ch;
#if COLOR
if (dtype != CDMONO)
rg.h.bl = cfcolor;
else
rg.h.bl = 0x07;
#else
rg.h.bl = 0x07;
#endif
int86(0x10, &rg, &rg);
}
void ibmeeop(void)
{
int attr; /* attribute to fill screen with */
rg.h.ah = 6; /* scroll page up function code */
rg.h.al = 0; /* # lines to scroll (clear it) */
rg.x.cx = 0; /* upper left corner of scroll */
rg.x.dx = (term.t_nrow << 8) | (term.t_ncol - 1);
/* lower right corner of scroll */
#if COLOR
if (dtype != CDMONO)
attr =
((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15);
else
attr = 0;
#else
attr = 0;
#endif
rg.h.bh = attr;
int86(0x10, &rg, &rg);
}
/* Change reverse video state.
*
* @state: TRUE = reverse, FALSE = normal.
*/
void ibmrev(int state)
{
/* This never gets used under the IBM-PC driver */
}
/* Change screen resolution.
*
* @res: resolution to change to.
*/
void ibmcres(char *res)
{
int i;
for (i = 0; i < NDRIVE; i++) {
if (strcmp(res, drvname[i]) == 0) {
scinit(i);
return TRUE;
}
}
return FALSE;
}
#if SCROLLCODE
/* Move howmany lines starting at from to to. */
void ibmscroll_reg(from, to, howmany)
{
int i;
if (to < from) {
for (i = 0; i < howmany; i++) {
movmem(scptr[from + i], scptr[to + i],
term.t_ncol * 2);
}
}
else if (to > from) {
for (i = howmany - 1; i >= 0; i--) {
movmem(scptr[from + i], scptr[to + i],
term.t_ncol * 2);
}
}
}
#endif
void ibmbeep(void)
{
bdos(6, BEL, 0);
}
void ibmopen(void)
{
scinit(CDSENSE);
revexist = TRUE;
ttopen();
}
void ibmclose(void)
{
#if COLOR
ibmfcol(7);
ibmbcol(0);
#endif
/* if we had the EGA open... close it */
if (dtype == CDEGA)
egaclose();
#if PKCODE
if (dtype == CDVGA)
egaclose();
#endif
ttclose();
}
/* Open the keyboard. */
void ibmkopen(void)
{
}
/* Close the keyboard. */
void ibmkclose(void)
{
}
/* Initialize the screen head pointers.
*
* @type: type of adapter to init for.
*/
static int scinit(int type)
{
union {
long laddr; /* long form of address */
int *paddr; /* pointer form of address */
} addr;
int i;
/* if asked...find out what display is connected */
if (type == CDSENSE)
type = getboard();
/* if we have nothing to do....don't do it */
if (dtype == type)
return TRUE;
/* if we try to switch to EGA and there is none, don't */
if (type == CDEGA && egaexist != TRUE)
return FALSE;
/* if we had the EGA open... close it */
if (dtype == CDEGA)
egaclose();
#if PKCODE
if (dtype == CDVGA)
egaclose();
#endif
/* and set up the various parameters as needed */
switch (type) {
case CDMONO: /* Monochrome adapter */
scadd = SCADM;
newsize(TRUE, 25);
break;
case CDCGA: /* Color graphics adapter */
scadd = SCADC;
newsize(TRUE, 25);
break;
case CDEGA: /* Enhanced graphics adapter */
scadd = SCADE;
egaopen();
newsize(TRUE, 43);
break;
case CDVGA: /* Enhanced graphics adapter */
scadd = SCADE;
egaopen();
newsize(TRUE, 50);
break;
}
/* reset the $sres environment variable */
strcpy(sres, drvname[type]);
dtype = type;
/* initialize the screen pointer array */
for (i = 0; i < NROW; i++) {
addr.laddr = scadd + (long) (NCOL * i * 2);
scptr[i] = addr.paddr;
}
return TRUE;
}
/* getboard: Determine which type of display board is attached.
Current known types include:
CDMONO Monochrome graphics adapter
CDCGA Color Graphics Adapter
CDEGA Extended graphics Adapter
*/
/* getboard: Detect the current display adapter
if MONO set to MONO
CGA set to CGA EGAexist = FALSE
EGA set to CGA EGAexist = TRUE
*/
int getboard(void)
{
int type; /* board type to return */
type = CDCGA;
int86(0x11, &rg, &rg);
if ((((rg.x.ax >> 4) & 3) == 3))
type = CDMONO;
/* test if EGA present */
rg.x.ax = 0x1200;
rg.x.bx = 0xff10;
int86(0x10, &rg, &rg); /* If EGA, bh=0-1 and bl=0-3 */
egaexist = !(rg.x.bx & 0xfefc); /* Yes, it's EGA */
return type;
}
/* init the computer to work with the EGA */
void egaopen(void)
{
/* put the beast into EGA 43 row mode */
rg.x.ax = 3;
int86(16, &rg, &rg);
rg.h.ah = 17; /* set char. generator function code */
rg.h.al = 18; /* to 8 by 8 double dot ROM */
rg.h.bl = 0; /* block 0 */
int86(16, &rg, &rg);
rg.h.ah = 18; /* alternate select function code */
rg.h.al = 0; /* clear AL for no good reason */
rg.h.bl = 32; /* alt. print screen routine */
int86(16, &rg, &rg);
rg.h.ah = 1; /* set cursor size function code */
rg.x.cx = 0x0607; /* turn cursor on code */
int86(0x10, &rg, &rg);
outp(0x3d4, 10); /* video bios bug patch */
outp(0x3d5, 6);
}
void egaclose(void)
{
/* put the beast into 80 column mode */
rg.x.ax = 3;
int86(16, &rg, &rg);
}
/* Write a line out.
*
* @row: row of screen to place outstr on.
* @outstr: string to write out (must be term.t_ncol long).
* @forg: forground color of string to write.
* @bacg: background color.
*/
void scwrite(int row, char *outstr, int forg, int bacg)
{
unsigned int attr; /* attribute byte mask to place in RAM */
unsigned int *lnptr; /* pointer to the destination line */
int i;
/* build the attribute byte and setup the screen pointer */
#if COLOR
if (dtype != CDMONO)
attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8;
else
attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
#else
attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
#endif
lnptr = &sline[0];
for (i = 0; i < term.t_ncol; i++)
*lnptr++ = (outstr[i] & 255) | attr;
if (flickcode && (dtype == CDCGA)) {
/* wait for vertical retrace to be off */
while ((inp(0x3da) & 8));
/* and to be back on */
while ((inp(0x3da) & 8) == 0);
}
/* and send the string out */
movmem(&sline[0], scptr[row], term.t_ncol * 2);
}
#endif

488
fridge/vmsvt.c Normal file
View File

@ -0,0 +1,488 @@
/* VMSVT.C
*
* Advanced VMS terminal driver
*
* Knows about any terminal defined in SMGTERMS.TXT and TERMTABLE.TXT
* located in SYS$SYSTEM.
*
* Author: Curtis Smith
* modified by Petri Kutvonen
*/
#include <stdio.h> /* Standard I/O package */
#include "estruct.h" /* Emacs' structures */
#if VMSVT
#include <descrip.h> /* Descriptor definitions */
/* These would normally come from iodef.h and ttdef.h */
#define IO$_SENSEMODE 0x27 /* Sense mode of terminal */
#define TT$_UNKNOWN 0x00 /* Unknown terminal */
#define TT$_VT100 96
/** Forward references **/
int vmsopen(), ttclose(), vmskopen(), vmskclose(), ttgetc(), ttputc();
int ttflush(), vmsmove(), vmseeol(), vmseeop(), vmsbeep(), vmsrev();
int vmscres();
extern int eolexist, revexist;
extern char sres[];
#if COLOR
int vmsfcol(), vmsbcol();
#endif
/** SMG stuff **/
static char *begin_reverse, *end_reverse, *erase_to_end_line;
static char *erase_whole_display;
static int termtype;
#define SMG$K_BEGIN_REVERSE 0x1bf
#define SMG$K_END_REVERSE 0x1d6
#define SMG$K_SET_CURSOR_ABS 0x23a
#define SMG$K_ERASE_WHOLE_DISPLAY 0x1da
#define SMG$K_ERASE_TO_END_LINE 0x1d9
#if SCROLLCODE
#define SMG$K_SCROLL_FORWARD 561 /* from sys$library:smgtrmptr.h */
#define SMG$K_SCROLL_REVERSE 562
#define SMG$K_SET_SCROLL_REGION 572
static char *scroll_forward, *scroll_reverse;
#endif
/* Dispatch table. All hard fields just point into the terminal I/O code. */
struct terminal term = {
#if PKCODE
MAXROW,
#else
24 - 1, /* Max number of rows allowable */
#endif
/* Filled in */ -1,
/* Current number of rows used */
MAXCOL, /* Max number of columns */
/* Filled in */ 0,
/* Current number of columns */
64, /* Min margin for extended lines */
8, /* Size of scroll region */
100, /* # times thru update to pause */
vmsopen, /* Open terminal at the start */
ttclose, /* Close terminal at end */
vmskopen, /* Open keyboard */
vmskclose, /* Close keyboard */
ttgetc, /* Get character from keyboard */
ttputc, /* Put character to display */
ttflush, /* Flush output buffers */
vmsmove, /* Move cursor, origin 0 */
vmseeol, /* Erase to end of line */
vmseeop, /* Erase to end of page */
vmsbeep, /* Beep */
vmsrev, /* Set reverse video state */
vmscres /* Change screen resolution */
#if COLOR
, vmsfcol, /* Set forground color */
vmsbcol /* Set background color */
#endif
#if SCROLLCODE
, NULL
#endif
};
/***
* ttputs - Send a string to ttputc
*
* Nothing returned
***/
ttputs(string)
char *string; /* String to write */
{
if (string)
while (*string != '\0')
ttputc(*string++);
}
/***
* vmsmove - Move the cursor (0 origin)
*
* Nothing returned
***/
vmsmove(row, col)
int row; /* Row position */
int col; /* Column position */
{
char buffer[32];
int ret_length;
static int request_code = SMG$K_SET_CURSOR_ABS;
static int max_buffer_length = sizeof(buffer);
static int arg_list[3] = { 2 };
char *cp;
int i;
/* Set the arguments into the arg_list array
* SMG assumes the row/column positions are 1 based (boo!)
*/
arg_list[1] = row + 1;
arg_list[2] = col + 1;
if ((smg$get_term_data( /* Get terminal data */
&termtype, /* Terminal table address */
&request_code, /* Request code */
&max_buffer_length, /* Maximum buffer length */
&ret_length, /* Return length */
buffer, /* Capability data buffer */
arg_list)
/* Argument list array */
/* We'll know soon enough if this doesn't work */
&1) == 0) {
ttputs("OOPS");
return;
}
/* Send out resulting sequence */
i = ret_length;
cp = buffer;
while (i-- > 0)
ttputc(*cp++);
}
#if SCROLLCODE
vmsscroll_reg(from, to, howmany)
{
int i;
if (to == from)
return;
if (to < from) {
vmsscrollregion(to, from + howmany - 1);
vmsmove(from + howmany - 1, 0);
for (i = from - to; i > 0; i--)
ttputs(scroll_forward);
} else { /* from < to */
vmsscrollregion(from, to + howmany - 1);
vmsmove(from, 0);
for (i = to - from; i > 0; i--)
ttputs(scroll_reverse);
}
vmsscrollregion(-1, -1);
}
vmsscrollregion(top, bot)
int top; /* Top position */
int bot; /* Bottom position */
{
char buffer[32];
int ret_length;
static int request_code = SMG$K_SET_SCROLL_REGION;
static int max_buffer_length = sizeof(buffer);
static int arg_list[3] = { 2 };
char *cp;
int i;
/* Set the arguments into the arg_list array
* SMG assumes the row/column positions are 1 based (boo!)
*/
arg_list[1] = top + 1;
arg_list[2] = bot + 1;
if ((smg$get_term_data( /* Get terminal data */
&termtype, /* Terminal table address */
&request_code, /* Request code */
&max_buffer_length, /* Maximum buffer length */
&ret_length, /* Return length */
buffer, /* Capability data buffer */
arg_list)
/* Argument list array */
/* We'll know soon enough if this doesn't work */
&1) == 0) {
ttputs("OOPS");
return;
}
ttputc(0);
/* Send out resulting sequence */
i = ret_length;
cp = buffer;
while (i-- > 0)
ttputc(*cp++);
}
#endif
/***
* vmsrev - Set the reverse video status
*
* Nothing returned
***/
vmsrev(status)
int status; /* TRUE if setting reverse */
{
if (status)
ttputs(begin_reverse);
else
ttputs(end_reverse);
}
/***
* vmscres - Change screen resolution (which it doesn't)
*
* Nothing returned
***/
vmscres()
{
/* But it could. For vt100/vt200s, one could switch from
80 and 132 columns modes */
}
#if COLOR
/***
* vmsfcol - Set the forground color (not implimented)
*
* Nothing returned
***/
vmsfcol()
{
}
/***
* vmsbcol - Set the background color (not implimented)
*
* Nothing returned
***/
vmsbcol()
{
}
#endif
/***
* vmseeol - Erase to end of line
*
* Nothing returned
***/
vmseeol()
{
ttputs(erase_to_end_line);
}
/***
* vmseeop - Erase to end of page (clear screen)
*
* Nothing returned
***/
vmseeop()
{
ttputs(erase_whole_display);
}
/***
* vmsbeep - Ring the bell
*
* Nothing returned
***/
vmsbeep()
{
ttputc('\007');
}
/***
* vmsgetstr - Get an SMG string capability by name
*
* Returns: Escape sequence
* NULL No escape sequence available
***/
char *vmsgetstr(request_code)
int request_code; /* Request code */
{
char *result;
static char seq_storage[1024];
static char *buffer = seq_storage;
static int arg_list[2] = { 1, 1 };
int max_buffer_length, ret_length;
/* Precompute buffer length */
max_buffer_length = (seq_storage + sizeof(seq_storage)) - buffer;
/* Get terminal commands sequence from master table */
if ((smg$get_term_data( /* Get terminal data */
&termtype, /* Terminal table address */
&request_code, /* Request code */
&max_buffer_length, /* Maximum buffer length */
&ret_length, /* Return length */
buffer, /* Capability data buffer */
arg_list)
/* Argument list array */
/* If this doesn't work, try again with no arguments */
&1) == 0 && (smg$get_term_data( /* Get terminal data */
&termtype, /* Terminal table address */
&request_code, /* Request code */
&max_buffer_length, /* Maximum buffer length */
&ret_length, /* Return length */
buffer)
/* Capability data buffer */
/* Return NULL pointer if capability is not available */
&1) == 0)
return NULL;
/* Check for empty result */
if (ret_length == 0)
return NULL;
/* Save current position so we can return it to caller */
result = buffer;
/* NIL terminate the sequence for return */
buffer[ret_length] = 0;
/* Advance buffer */
buffer += ret_length + 1;
/* Return capability to user */
return result;
}
/** I/O information block definitions **/
struct iosb { /* I/O status block */
short i_cond; /* Condition value */
short i_xfer; /* Transfer count */
long i_info; /* Device information */
};
struct termchar { /* Terminal characteristics */
char t_class; /* Terminal class */
char t_type; /* Terminal type */
short t_width; /* Terminal width in characters */
long t_mandl; /* Terminal's mode and length */
long t_extend; /* Extended terminal characteristics */
};
static struct termchar tc; /* Terminal characteristics */
/***
* vmsgtty - Get terminal type from system control block
*
* Nothing returned
***/
vmsgtty()
{
short fd;
int status;
struct iosb iostatus;
$DESCRIPTOR(devnam, "SYS$INPUT");
/* Assign input to a channel */
status = sys$assign(&devnam, &fd, 0, 0);
if ((status & 1) == 0)
exit(status);
/* Get terminal characteristics */
status = sys$qiow( /* Queue and wait */
0, /* Wait on event flag zero */
fd, /* Channel to input terminal */
IO$_SENSEMODE, /* Get current characteristic */
&iostatus, /* Status after operation */
0, 0, /* No AST service */
&tc, /* Terminal characteristics buf */
sizeof(tc), /* Size of the buffer */
0, 0, 0, 0); /* P3-P6 unused */
/* De-assign the input device */
if ((sys$dassgn(fd) & 1) == 0)
exit(status);
/* Jump out if bad status */
if ((status & 1) == 0)
exit(status);
if ((iostatus.i_cond & 1) == 0)
exit(iostatus.i_cond);
}
/***
* vmsopen - Get terminal type and open terminal
*
* Nothing returned
***/
vmsopen()
{
/* Get terminal type */
vmsgtty();
if (tc.t_type == TT$_UNKNOWN) {
printf("Terminal type is unknown!\n");
printf
("Try set your terminal type with SET TERMINAL/INQUIRE\n");
printf("Or get help on SET TERMINAL/DEVICE_TYPE\n");
exit(3);
}
/* Access the system terminal definition table for the */
/* information of the terminal type returned by IO$_SENSEMODE */
if ((smg$init_term_table_by_type(&tc.t_type, &termtype) & 1) == 0)
return -1;
/* Set sizes */
term.t_nrow = ((unsigned int) tc.t_mandl >> 24) - 1;
term.t_ncol = tc.t_width;
/* Get some capabilities */
begin_reverse = vmsgetstr(SMG$K_BEGIN_REVERSE);
end_reverse = vmsgetstr(SMG$K_END_REVERSE);
revexist = begin_reverse != NULL && end_reverse != NULL;
erase_to_end_line = vmsgetstr(SMG$K_ERASE_TO_END_LINE);
eolexist = erase_to_end_line != NULL;
erase_whole_display = vmsgetstr(SMG$K_ERASE_WHOLE_DISPLAY);
#if SCROLLCODE
scroll_forward = vmsgetstr(SMG$K_SCROLL_FORWARD);
scroll_reverse = vmsgetstr(SMG$K_SCROLL_REVERSE);
if (tc.t_type < TT$_VT100 || scroll_reverse == NULL ||
scroll_forward == NULL)
term.t_scroll = NULL;
else
term.t_scroll = vmsscroll_reg;
#endif
/* Set resolution */
strcpy(sres, "NORMAL");
/* Open terminal I/O drivers */
ttopen();
}
/***
* vmskopen - Open keyboard (not used)
*
* Nothing returned
***/
vmskopen()
{
}
/***
* vmskclose - Close keyboard (not used)
*
* Nothing returned
***/
vmskclose()
{
}
#endif

161
fridge/vt52.c Normal file
View File

@ -0,0 +1,161 @@
/* vt52.c
*
* The routines in this file
* provide support for VT52 style terminals
* over a serial line. The serial I/O services are
* provided by routines in "termio.c". It compiles
* into nothing if not a VT52 style device. The
* bell on the VT52 is terrible, so the "beep"
* routine is conditionalized on defining BEL.
*
* modified by Petri Kutvonen
*/
#define termdef 1 /* don't define "term" external */
#include <stdio.h>
#include "estruct.h"
#if VT52
#define NROW 24 /* Screen size. */
#define NCOL 80 /* Edit if you want to. */
#define MARGIN 8 /* size of minimim margin and */
#define SCRSIZ 64 /* scroll size for extended lines */
#define NPAUSE 100 /* # times thru update to pause */
#define BIAS 0x20 /* Origin 0 coordinate bias. */
#define ESC 0x1B /* ESC character. */
#define BEL 0x07 /* ascii bell character */
extern int ttopen(); /* Forward references. */
extern int ttgetc();
extern int ttputc();
extern int ttflush();
extern int ttclose();
extern int vt52move();
extern int vt52eeol();
extern int vt52eeop();
extern int vt52beep();
extern int vt52open();
extern int vt52rev();
extern int vt52cres();
extern int vt52kopen();
extern int vt52kclose();
#if COLOR
extern int vt52fcol();
extern int vt52bcol();
#endif
/*
* Dispatch table.
* All the hard fields just point into the terminal I/O code.
*/
struct terminal term = {
NROW - 1,
NROW - 1,
NCOL,
NCOL,
MARGIN,
SCRSIZ,
NPAUSE,
&vt52open,
&ttclose,
&vt52kopen,
&vt52kclose,
&ttgetc,
&ttputc,
&ttflush,
&vt52move,
&vt52eeol,
&vt52eeop,
&vt52beep,
&vt52rev,
&vt52cres
#if COLOR
, &vt52fcol,
&vt52bcol
#endif
#if SCROLLCODE
, NULL
#endif
};
vt52move(row, col)
{
ttputc(ESC);
ttputc('Y');
ttputc(row + BIAS);
ttputc(col + BIAS);
}
vt52eeol()
{
ttputc(ESC);
ttputc('K');
}
vt52eeop()
{
ttputc(ESC);
ttputc('J');
}
vt52rev(status)
/* set the reverse video state */
int status; /* TRUE = reverse video, FALSE = normal video */
{
/* can't do this here, so we won't */
}
vt52cres()
{ /* change screen resolution - (not here though) */
return TRUE;
}
#if COLOR
vt52fcol()
{ /* set the forground color [NOT IMPLIMENTED] */
}
vt52bcol()
{ /* set the background color [NOT IMPLIMENTED] */
}
#endif
vt52beep()
{
#ifdef BEL
ttputc(BEL);
ttflush();
#endif
}
vt52open()
{
#if V7 | BSD
char *cp;
char *getenv();
if ((cp = getenv("TERM")) == NULL) {
puts("Shell variable TERM not defined!");
exit(1);
}
if (strcmp(cp, "vt52") != 0 && strcmp(cp, "z19") != 0) {
puts("Terminal type not 'vt52'or 'z19' !");
exit(1);
}
#endif
ttopen();
}
vt52kopen()
{
}
vt52kclose()
{
}
#endif

734
input.c
View File

@ -1,30 +1,36 @@
/* input.c -- implements input.h */ /* input.c -- implements input.h */
#include "input.h" #include "input.h"
/* Various input routines /* input.c
*
* Various input routines
* *
* written by Daniel Lawrence 5/9/86 * written by Daniel Lawrence 5/9/86
* modified by Petri Kutvonen * modified by Petri Kutvonen
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "bind.h" #include "bind.h"
#include "estruct.h"
#include "bindable.h" #include "bindable.h"
#include "defines.h" #include "display.h"
#include "display.h" /* rubout(), echos(), echoc(), update() */
#include "exec.h" #include "exec.h"
#include "isa.h"
#include "mlout.h"
#include "names.h" #include "names.h"
#include "terminal.h" #include "terminal.h"
#include "utf8.h" #include "utf8.h"
#include "wrapper.h" #include "wrapper.h"
#if PKCODE && UNIX #if PKCODE
#if MSDOS && TURBO
#include <dir.h>
#endif
#endif
#if PKCODE && (UNIX || (MSDOS && TURBO))
#define COMPLC 1 #define COMPLC 1
#else #else
#define COMPLC 0 #define COMPLC 0
@ -39,22 +45,18 @@ kbdstate kbdmode = STOP ; /* current keyboard macro mode */
int lastkey = 0 ; /* last keystoke */ int lastkey = 0 ; /* last keystoke */
int kbdrep = 0 ; /* number of repetitions */ int kbdrep = 0 ; /* number of repetitions */
int metac = CTL_ | '[' ; /* current meta character */ int disinp = TRUE ; /* display input characters */
int ctlxc = CTL_ | 'X' ; /* current control X prefix char */
int reptc = CTL_ | 'U' ; /* current universal repeat char */
int abortc = CTL_ | 'G' ; /* current abort command char */
const int nlc = CTL_ | 'J' ; /* end of input char */ int metac = CONTROL | '[' ; /* current meta character */
int ctlxc = CONTROL | 'X' ; /* current control X prefix char */
int reptc = CONTROL | 'U' ; /* current universal repeat char */
int abortc = CONTROL | 'G' ; /* current abort command char */
const int nlc = CONTROL | 'J' ; /* end of input char */
void ue_system( const char *cmd) { static const int quotec = 0x11 ; /* quote char during getstring() */
int ret ;
ret = system( cmd) ; static void outstring( char *s) ;
if( ret == -1) {
/* some actual handling needed here */
}
}
/* /*
* Ask a yes or no question in the message line. Return either TRUE, FALSE, or * Ask a yes or no question in the message line. Return either TRUE, FALSE, or
@ -63,16 +65,16 @@ void ue_system( const char *cmd) {
*/ */
int mlyesno( const char *prompt) int mlyesno( const char *prompt)
{ {
int c ; /* input character */ char c; /* input character */
for (;;) { for (;;) {
/* prompt the user */ /* prompt the user */
mloutfmt( "%s (y/n)? ", prompt) ; mlwrite( "%s (y/n)? ", prompt) ;
/* get the response */ /* get the response */
c = get1key() ; c = tgetc();
if( c == abortc) /* Bail out! */ if (c == ectoc(abortc)) /* Bail out! */
return ABORT; return ABORT;
if (c == 'y' || c == 'Y') if (c == 'y' || c == 'Y')
@ -143,16 +145,15 @@ int newmlargt( char **outbufref, const char *prompt, int size) {
/* /*
* ectoc: * ectoc:
* expanded character to character * expanded character to character
* collapse the CTL_ and SPEC flags back into an ascii code * collapse the CONTROL and SPEC flags back into an ascii code
*/ */
int ectoc( int c) { int ectoc(int c)
if( c & CTL_) {
c ^= CTL_ | 0x40 ; if (c & CONTROL)
c = c & ~(CONTROL | 0x40);
if( c & SPEC) if (c & SPEC)
c &= 255 ; c = c & 255;
return c;
return c ;
} }
/* /*
@ -160,11 +161,14 @@ int ectoc( int c) {
* that pressing a <SPACE> will attempt to complete an unfinished command * that pressing a <SPACE> will attempt to complete an unfinished command
* name if it is unique. * name if it is unique.
*/ */
nbind_p getname( void) { fn_t getname(void)
{
int cpos; /* current column on screen output */ int cpos; /* current column on screen output */
nbind_p ffp; /* first ptr to entry in name binding table */ int c;
nbind_p cffp; /* current ptr to entry in name binding table */ char *sp; /* pointer to string for output */
nbind_p lffp; /* last ptr to entry in name binding table */ struct name_bind *ffp; /* first ptr to entry in name binding table */
struct name_bind *cffp; /* current ptr to entry in name binding table */
struct name_bind *lffp; /* last ptr to entry in name binding table */
char buf[NSTRING]; /* buffer to hold tentative command name */ char buf[NSTRING]; /* buffer to hold tentative command name */
/* starting at the beginning of the string buffer */ /* starting at the beginning of the string buffer */
@ -174,13 +178,11 @@ nbind_p getname( void) {
if (clexec) { if (clexec) {
if( TRUE != gettokval( buf, sizeof buf)) if( TRUE != gettokval( buf, sizeof buf))
return NULL; return NULL;
return fncmatch( buf) ; return fncmatch(&buf[0]);
} }
/* build a name string from the keyboard */ /* build a name string from the keyboard */
while (TRUE) { while (TRUE) {
int c ;
c = tgetc(); c = tgetc();
/* if we are at the end, just match it */ /* if we are at the end, just match it */
@ -188,85 +190,116 @@ nbind_p getname( void) {
buf[cpos] = 0; buf[cpos] = 0;
/* and match it off */ /* and match it off */
return fncmatch( buf) ; return fncmatch(&buf[0]);
} else if( c == ectoc(abortc)) { /* Bell, abort */ } else if (c == ectoc(abortc)) { /* Bell, abort */
ctrlg( FALSE, 1) ; ctrlg(FALSE, 0);
TTflush() ; TTflush();
return NULL ; return NULL;
} else if (c == 0x7F || c == 0x08) { /* rubout/erase */ } else if (c == 0x7F || c == 0x08) { /* rubout/erase */
if (cpos != 0) { if (cpos != 0) {
rubout() ; TTputc('\b');
TTputc(' ');
TTputc('\b');
--ttcol;
--cpos; --cpos;
TTflush(); TTflush();
} }
} else if (c == 0x15) { /* C-U, kill */ } else if (c == 0x15) { /* C-U, kill */
while (cpos != 0) { while (cpos != 0) {
rubout() ; TTputc('\b');
TTputc(' ');
TTputc('\b');
--cpos; --cpos;
--ttcol;
} }
TTflush(); TTflush();
} else if (c == ' ' || c == 0x1b || c == 0x09) { } else if (c == ' ' || c == 0x1b || c == 0x09) {
/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
/* attempt a completion */ /* attempt a completion */
buf[ cpos] = 0 ; /* terminate it for us */ buf[cpos] = 0; /* terminate it for us */
int buflen = strlen( buf) ; ffp = &names[0]; /* scan for matches */
/* scan for matches */ while (ffp->n_func != NULL) {
for( ffp = names ; ffp->n_func != NULL ; ffp++) { if (strncmp(buf, ffp->n_name, strlen(buf))
if( strncmp( buf, bind_name( ffp), buflen) == 0) { == 0) {
/* a possible match! More than one? */ /* a possible match! More than one? */
if( (ffp + 1)->n_func == NULL || if ((ffp + 1)->n_func == NULL ||
(strncmp( buf, bind_name( ffp + 1), buflen) != 0)) { (strncmp
(buf, (ffp + 1)->n_name,
strlen(buf)) != 0)) {
/* no...we match, print it */ /* no...we match, print it */
echos( &bind_name( ffp)[ cpos]) ; sp = ffp->n_name + cpos;
TTflush() ; while (*sp)
return ffp ; TTputc(*sp++);
TTflush();
return ffp->n_func;
} else { } else {
/* << << << << << << << << << << << << << << << << << */ /* << << << << << << << << << << << << << << << << << */
/* try for a partial match against the list */ /* try for a partial match against the list */
/* first scan down until we no longer match the /* first scan down until we no longer match the current input */
* current input */ lffp = (ffp + 1);
for( lffp = ffp + 1 ; (lffp + 1)->n_func != NULL ; while ((lffp +
lffp++) 1)->n_func !=
if( strncmp( buf, bind_name( lffp + 1), NULL) {
buflen) != 0) if (strncmp
break ; (buf,
(lffp +
1)->n_name,
strlen(buf))
!= 0)
break;
++lffp;
}
/* and now, attempt to partial complete the string, /* and now, attempt to partial complete the string, char at a time */
* one char at a time */
while (TRUE) { while (TRUE) {
/* add the next char in */ /* add the next char in */
buf[ cpos] = bind_name( ffp)[ cpos] ; buf[cpos] =
ffp->
n_name[cpos];
/* scan through the candidates */ /* scan through the candidates */
for( cffp = ffp + 1 ; cffp <= lffp ; cffp++) cffp = ffp + 1;
if( bind_name( cffp)[ cpos] != buf[ cpos]) while (cffp <=
goto onward ; lffp) {
if (cffp->
n_name
[cpos]
!=
buf
[cpos])
goto onward;
++cffp;
}
/* add the character */ /* add the character */
echoc( buf[ cpos++]) ; TTputc(buf
[cpos++]);
} }
/* << << << << << << << << << << << << << << << << << */ /* << << << << << << << << << << << << << << << << << */
} }
} }
++ffp;
} }
/* no match.....beep and onward */ /* no match.....beep and onward */
TTbeep(); TTbeep();
onward: onward:;
TTflush(); TTflush();
/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
} else { } else {
if( cpos < NSTRING - 1 && (islower( c) || c == '-')) { if (cpos < NSTRING - 1 && c > ' ') {
buf[cpos++] = c; buf[cpos++] = c;
echoc( c) ; TTputc(c);
TTflush();
} }
++ttcol;
TTflush();
} }
} }
} }
@ -285,7 +318,7 @@ int tgetc(void)
if (kbdptr < kbdend) if (kbdptr < kbdend)
return (int) *kbdptr++; return (int) *kbdptr++;
/* at the end of last repetition? */ /* at the end of last repitition? */
if (--kbdrep < 1) { if (--kbdrep < 1) {
kbdmode = STOP; kbdmode = STOP;
#if VISMAC == 0 #if VISMAC == 0
@ -322,181 +355,172 @@ int tgetc(void)
return c; return c;
} }
/* GET1KEY: Get one keystroke. The only prefixes legal here are the SPEC /* GET1KEY: Get one keystroke. The only prefixs legal here
and CTL_ prefixes. */ are the SPEC and CONTROL prefixes.
static int get1unicode( int *up) { */
/* Accept UTF-8 sequence */
int bytes ;
int c = tgetc() ; int get1key(void)
if( c > 0xC1 && c <= 0xF4) { {
int c;
/* get a keystroke */
c = tgetc();
#if MSDOS
if (c == 0) { /* Apply SPEC prefix */
c = tgetc();
if (c >= 0x00 && c <= 0x1F) /* control key? */
c = CONTROL | (c + '@');
return SPEC | c;
}
#endif
if (c >= 0x00 && c <= 0x1F) /* C0 control -> C- */
c = CONTROL | (c + '@');
return c;
}
/* GETCMD: Get a command from the keyboard. Process all applicable
prefix keys
*/
int getcmd(void)
{
int c; /* fetched keystroke */
#if VT220
int d; /* second character P.K. */
int cmask = 0;
#endif
/* get initial character */
c = get1key();
#if VT220
proc_metac:
#endif
if (c == 128+27) /* CSI */
goto handle_CSI;
/* process META prefix */
if (c == (CONTROL | '[')) {
c = get1key();
#if VT220
if (c == '[' || c == 'O') { /* CSI P.K. */
handle_CSI:
c = get1key();
if (c >= 'A' && c <= 'D')
return SPEC | c | cmask;
if (c >= 'E' && c <= 'z' && c != 'i' && c != 'c')
return SPEC | c | cmask;
d = get1key();
if (d == '~') /* ESC [ n ~ P.K. */
return SPEC | c | cmask;
switch (c) { /* ESC [ n n ~ P.K. */
case '1':
c = d + 32;
break;
case '2':
c = d + 48;
break;
case '3':
c = d + 64;
break;
default:
c = '?';
break;
}
if (d != '~') /* eat tilde P.K. */
get1key();
if (c == 'i') { /* DO key P.K. */
c = ctlxc;
goto proc_ctlxc;
} else if (c == 'c') /* ESC key P.K. */
c = get1key();
else
return SPEC | c | cmask;
}
#endif
#if VT220
if (c == (CONTROL | '[')) {
cmask = META;
goto proc_metac;
}
#endif
if (islower(c)) /* Force to upper */
c ^= DIFCASE;
if (c >= 0x00 && c <= 0x1F) /* control key */
c = CONTROL | (c + '@');
return META | c;
}
#if PKCODE
else if (c == metac) {
c = get1key();
#if VT220
if (c == (CONTROL | '[')) {
cmask = META;
goto proc_metac;
}
#endif
if (islower(c)) /* Force to upper */
c ^= DIFCASE;
if (c >= 0x00 && c <= 0x1F) /* control key */
c = CONTROL | (c + '@');
return META | c;
}
#endif
#if VT220
proc_ctlxc:
#endif
/* process CTLX prefix */
if (c == ctlxc) {
c = get1key();
#if VT220
if (c == (CONTROL | '[')) {
cmask = CTLX;
goto proc_metac;
}
#endif
if (c >= 'a' && c <= 'z') /* Force to upper */
c -= 0x20;
if (c >= 0x00 && c <= 0x1F) /* control key */
c = CONTROL | (c + '@');
return CTLX | c;
}
#ifdef CYGWIN
/* Accept UTF-8 sequence */
if( c <= 0xC1 || c > 0xF4)
return c ;
else {
char utf[ 4] ; char utf[ 4] ;
char cc ; char cc ;
utf[ 0] = c ; utf[ 0] = c ;
utf[ 1] = cc = tgetc() ; utf[ 1] = cc = get1key() ;
if( (c & 0x20) && ((cc & 0xC0) == 0x80)) { /* at least 3 bytes and a valid encoded char */ if( (c & 0x20) && ((cc & 0xC0) == 0x80)) { /* at least 3 bytes and a valid encoded char */
utf[ 2] = cc = tgetc() ; utf[ 2] = cc = get1key() ;
if( (c & 0x10) && ((cc & 0xC0) == 0x80)) /* at least 4 bytes and a valid encoded char */ if( (c & 0x10) && ((cc & 0xC0) == 0x80)) /* at least 4 bytes and a valid encoded char */
utf[ 3] = tgetc() ; utf[ 3] = get1key() ;
} }
bytes = utf8_to_unicode( utf, 0, sizeof utf, (unicode_t *) up) ; utf8_to_unicode( utf, 0, sizeof utf, (unicode_t *) &c) ;
} else {
if( (c >= 0x00 && c <= 0x1F) || c == 0x7F) /* C0 control -> C- */
c ^= CTL_ | 0x40 ;
*up = c ;
bytes = 1 ;
} }
#endif
return bytes ;
} /* otherwise, just return it */
return c;
/* Terminal sequences need up to 7 read ahead characters */
#define STACKSIZE 7
static int keystack[ STACKSIZE] ;
static int *stackptr = &keystack[ STACKSIZE] ;
#define KPUSH( c) *(--stackptr) = (c)
int get1key( void) {
int c ;
/* fetch from queue if any were pushed back */
if( stackptr != &keystack[ STACKSIZE])
return *(stackptr++) ;
/* fetch from keyboard */
get1unicode( &c) ;
return c ;
}
/* GETCMD: Get a command from the keyboard. Process all applicable prefix
keys. Handle alted and controlled FNx, not shifted.
*/
int getcmd( void) {
int prefix = 0 ; /* prefixes M- or ^X */
int keyread[ STACKSIZE] ; /* room to process sequences like ^[[24;2~ */
int *kptr = keyread ;
int c ;
for( ;;) {
c = *(kptr++) = get1key() ;
if( c == 0x9B)
goto foundCSI ;
else if( c == (CTL_ | '[')) {
/* fetch terminal sequence */
c = *(kptr++) = get1key() ;
if( c == 'O') { /* F1 .. F4 */
c = *(kptr++) = get1key() ;
if( c >= 'P' && c <= 'S')
return c | SPEC | prefix ;
} else if( c == '[') {
int v1, v ; /* ^[[v1;v~ or ^[[v~ */
foundCSI:
v1 = v = 0 ;
while( kptr < &keyread[ STACKSIZE]) {
c = *(kptr++) = get1key() ;
if( (c == '~')
|| (c >= 'A' && c <= 'Z')
|| (c >= 'a' && c <= 'z')) {
/* Found end of sequence */
int mask = prefix ;
if( v1) { /* Handle ALT/CTL, not SHFT */
if( (v - 1) & 2)
mask = META ;
if( (v - 1) & 4)
mask |= CTL_ ;
v = v1 ;
}
if( c == '~') {
if( v)
c = v + ((v <= 9) ? '0' : 'a' - 10) ;
else
break ;
}
return c | SPEC | mask ;
} else if( c == ';') { /* Start of SHFT/ALT/CTL state */
v1 = v ;
v = 0 ;
} else if( c >= '0' && c <= '9')
v = v * 10 + c - '0' ;
else
break ;
}
}
/* not a match, unget the keys read so far */
while( kptr > keyread)
KPUSH( *(--kptr)) ;
c = get1key() ;
} else
kptr-- ;
if( c == metac) {
prefix = META ;
} else if( c == ctlxc) {
if( prefix)
break ; /* ^X^X or M-^X */
else
prefix = CTLX ;
} else
break ;
}
if( prefix && islower( c))
c = flipcase( c) ;
return c | prefix ;
} }
/* A more generalized prompt/reply function allowing the caller /* A more generalized prompt/reply function allowing the caller
to specify the proper terminator. If the terminator is not to specify the proper terminator. If the terminator is not
a return ('\n') it will echo as "<NL>" a return ('\n') it will echo as "<NL>"
*/ */
static void echov( int c) {
/* verbose echo of a character */
if( c == '\n') /* put out <NL> for <ret> */
echos( "<NL>") ;
else {
if( c < ' ' || c == 0x7F) {
echoc( '^') ;
c ^= 0x40 ;
}
echoc( c) ;
}
}
static void rubc( int c) {
rubout() ;
if( (c >= 0 && c < ' ') || c == 0x7F) {
/* ^x range */
rubout() ;
if( c == '\n') { /* <NL> */
rubout() ;
rubout() ;
}
} else if( utf8_width( c) == 2)
rubout() ;
}
int getstring( const char *prompt, char *buf, int nbuf, int eolchar) int getstring( const char *prompt, char *buf, int nbuf, int eolchar)
{ {
int cpos; /* current character position in string */ int cpos; /* current character position in string */
int c; int c;
boolean quote_f ; /* are we quoting the next char? */ boolean quotef ; /* are we quoting the next char? */
int retval ; /* TRUE, FALSE, ABORT */
#if COMPLC #if COMPLC
boolean file_f ; int ffile, ocpos, nskip = 0, didtry = 0;
int ocpos, nskip = 0, didtry = 0;
#if MSDOS #if MSDOS
struct ffblk ffblk; struct ffblk ffblk;
char *fcp; char *fcp;
@ -505,16 +529,19 @@ int getstring( const char *prompt, char *buf, int nbuf, int eolchar)
static char tmp[] = "/tmp/meXXXXXX"; static char tmp[] = "/tmp/meXXXXXX";
FILE *tmpf = NULL; FILE *tmpf = NULL;
#endif #endif
/* Look for "find-file: ", "View file: ", "Insert file: ", "Write file: ", ffile = (strcmp(prompt, "Find file: ") == 0
** "Read file: ", "Execute file: " */ || strcmp(prompt, "View file: ") == 0
file_f = NULL != strstr( prompt, "file: ") ; || strcmp(prompt, "Insert file: ") == 0
|| strcmp(prompt, "Write file: ") == 0
|| strcmp(prompt, "Read file: ") == 0
|| strcmp(prompt, "File to execute: ") == 0);
#endif #endif
cpos = 0; cpos = 0;
quote_f = FALSE; quotef = FALSE;
/* prompt the user for the input string */ /* prompt the user for the input string */
mloutstr( prompt); mlwrite( "%s", prompt);
for (;;) { for (;;) {
#if COMPLC #if COMPLC
@ -522,63 +549,89 @@ int getstring( const char *prompt, char *buf, int nbuf, int eolchar)
nskip = -1; nskip = -1;
didtry = 0; didtry = 0;
#endif #endif
/* get a character from the user */ /* get a character from the user */
int bytes = get1unicode( &c) ; c = get1key();
/* Quoting? Store as it is */ /* If it is a <ret>, change it to a <NL> */
if( quote_f == TRUE) { #if PKCODE
quote_f = FALSE ; if (c == (CONTROL | 0x4d) && !quotef)
if( cpos < nbuf - bytes) { #else
c = ectoc( c) ; if (c == (CONTROL | 0x4d))
cpos += unicode_to_utf8( c, &buf[ cpos]) ; #endif
echov( c) ; c = CONTROL | 0x40 | '\n';
TTflush() ;
/* if they hit the line terminate, wrap it up */
if (c == eolchar && quotef == FALSE) {
buf[cpos++] = 0;
/* clear the message line */
mlwrite("");
TTflush();
if( tmpf != NULL) {
fclose( tmpf) ;
unlink( tmp) ;
} }
continue ; /* if we default the buffer, return FALSE */
} if (buf[0] == 0)
return FALSE;
/* If it is a <ret>, change it to a <NL> */ return TRUE;
if( c == (CTL_ | 'M')) }
c = CTL_ | 0x40 | '\n' ;
if( c == eolchar) { /* change from command form back to character form */
/* if they hit the line terminator, wrap it up */ c = ectoc(c);
buf[ cpos] = 0 ;
/* clear the message line */ if (c == ectoc(abortc) && quotef == FALSE) {
mloutstr( "") ; /* Abort the input? */
ctrlg(FALSE, 0);
TTflush();
if( tmpf != NULL) {
fclose( tmpf) ;
unlink( tmp) ;
}
/* if we default the buffer, return FALSE */ return ABORT;
retval = cpos != 0 ; } else if ((c == 0x7F || c == 0x08) && quotef == FALSE) {
break ; /* rubout/erase */
} else if( c == abortc) {
/* Abort the input? */
retval = ctrlg( FALSE, 1) ;
break ;
}
/* change from command form back to character form */
c = ectoc( c) ;
if( c == 0x7F || c == 0x08) {
/* rubout/erase */
if (cpos != 0) { if (cpos != 0) {
int c ; outstring("\b \b");
--ttcol;
if (buf[--cpos] < 0x20) {
outstring("\b \b");
--ttcol;
}
if (buf[cpos] == '\n') {
outstring("\b\b \b\b");
ttcol -= 2;
}
cpos -= 1 ;
cpos -= utf8_revdelta( (unsigned char *) &buf[ cpos], cpos) ;
utf8_to_unicode( &buf[ cpos], 0, 4, (unicode_t *) &c) ;
rubc( c) ;
TTflush(); TTflush();
} }
} else if( c == 0x15) {
/* C-U, kill */ } else if (c == 0x15 && quotef == FALSE) {
mloutstr( prompt) ; /* C-U, kill */
cpos = 0 ; while (cpos != 0) {
outstring("\b \b");
--ttcol;
if (buf[--cpos] < 0x20) {
outstring("\b \b");
--ttcol;
}
if (buf[cpos] == '\n') {
outstring("\b\b \b\b");
ttcol -= 2;
}
}
TTflush();
#if COMPLC #if COMPLC
} else if( (c == 0x09 || c == ' ') && file_f) { } else if ((c == 0x09 || c == ' ') && quotef == FALSE
/* TAB, complete file name */ && ffile) {
/* TAB, complete file name */
char ffbuf[255]; char ffbuf[255];
#if MSDOS #if MSDOS
char sffbuf[128]; char sffbuf[128];
@ -588,16 +641,29 @@ int getstring( const char *prompt, char *buf, int nbuf, int eolchar)
didtry = 1; didtry = 1;
ocpos = cpos; ocpos = cpos;
mloutstr( prompt) ; while (cpos != 0) {
while( cpos != 0) { outstring("\b \b");
c = buf[ --cpos] ; --ttcol;
if( c == '*' || c == '?') {
iswild = 1 ;
cpos = 0 ;
break ;
}
}
if (buf[--cpos] < 0x20) {
outstring("\b \b");
--ttcol;
}
if (buf[cpos] == '\n') {
outstring("\b\b \b\b");
ttcol -= 2;
}
if (buf[cpos] == '*' || buf[cpos] == '?')
iswild = 1;
#if MSDOS
if (lsav < 0 && (buf[cpos] == '\\' ||
buf[cpos] == '/' ||
buf[cpos] == ':'
&& cpos == 1))
lsav = cpos;
#endif
}
TTflush();
if (nskip < 0) { if (nskip < 0) {
buf[ocpos] = 0; buf[ocpos] = 0;
#if UNIX #if UNIX
@ -668,37 +734,75 @@ int getstring( const char *prompt, char *buf, int nbuf, int eolchar)
TTbeep(); TTbeep();
#endif #endif
for( n = 0 ; n < cpos ; ) { for (n = 0; n < cpos; n++) {
n += utf8_to_unicode( buf, n, nbuf, (unicode_t *) &c) ; c = buf[n];
echov( c) ; if ((c < ' ') && (c != '\n')) {
} outstring("^");
++ttcol;
c ^= 0x40;
}
TTflush() ; if (c != '\n') {
if (disinp)
TTputc(c);
} else { /* put out <NL> for <ret> */
outstring("<NL>");
ttcol += 3;
}
++ttcol;
}
TTflush();
#if UNIX #if UNIX
rewind(tmpf); rewind(tmpf);
#endif #endif
#endif #endif
} else if( c == 0x11 || c == 0x16) } else if ((c == quotec || c == 0x16) && quotef == FALSE) {
/* ^Q or ^V */ quotef = TRUE;
quote_f = TRUE ; } else {
else { quotef = FALSE;
/* store as it is */ if (cpos < nbuf - 1) {
if( cpos + bytes < nbuf) { buf[cpos++] = c;
cpos += unicode_to_utf8( c, &buf[ cpos]) ;
echov( c) ; if ((c < ' ') && (c != '\n')) {
TTflush() ; outstring("^");
++ttcol;
c ^= 0x40;
}
if (c != '\n') {
if (disinp)
TTputc(c);
} else { /* put out <NL> for <ret> */
outstring("<NL>");
ttcol += 3;
}
++ttcol;
TTflush();
} }
} }
} }
TTflush() ;
if( tmpf != NULL) {
fclose( tmpf) ;
unlink( tmp) ;
}
return retval ;
} }
/* end of input.c */ /*
* output a string of characters when display input is enabled
*
* char *s; string to output
*/
static void outstring( char *s) {
if( disinp)
while( *s)
TTputc( *s++) ;
}
/*
* output a string of output characters
*
* char *s; string to output
*/
void ostring( char *s)
{
if (discmd)
while (*s)
TTputc( *s++ & 0xFF) ;
}

41
input.h
View File

@ -1,41 +1,36 @@
/* input.h -- */
#ifndef _INPUT_H_ #ifndef _INPUT_H_
#define _INPUT_H_ #define _INPUT_H_
#include "names.h" /* nbind_p */ #include "bind.h"
typedef enum { typedef enum {
STOP, PLAY, RECORD STOP, PLAY, RECORD
} kbdstate ; } kbdstate ;
extern kbdstate kbdmode ; /* current keyboard macro mode */
extern int lastkey ; /* last keystoke */
extern int kbdrep ; /* number of repetitions */
extern int kbdm[] ; /* Holds kayboard macro data */
extern int *kbdptr ; /* current position in keyboard buf */
extern int *kbdend ; /* ptr to end of the keyboard */
extern int disinp ; /* display input characters */
extern int metac; /* current meta character */
extern int ctlxc; /* current control X prefix char */
extern int reptc; /* current universal repeat char */
extern int abortc; /* current abort command char */
extern const int nlc ; /* end of input char */
extern kbdstate kbdmode ; /* current keyboard macro mode */
extern int lastkey ; /* last keystoke */
extern int kbdrep ; /* number of repetitions */
extern int kbdm[] ; /* Holds kayboard macro data */
extern int *kbdptr ; /* current position in keyboard buf */
extern int *kbdend ; /* ptr to end of the keyboard */
extern int metac ; /* current meta character */
extern int ctlxc ; /* current control X prefix char */
extern int reptc ; /* current universal repeat char */
extern int abortc ; /* current abort command char */
extern const int nlc ; /* end of input char */
void ue_system( const char *cmd) ;
int mlyesno( const char *prompt) ; int mlyesno( const char *prompt) ;
int newmlarg( char **outbufref, const char *prompt, int size) ; int newmlarg( char **outbufref, const char *prompt, int size) ;
int newmlargt( char **outbufref, const char *prompt, int size) ; int newmlargt( char **outbufref, const char *prompt, int size) ;
int ectoc( int c) ; int ectoc( int c) ;
fn_t getname( void) ;
/* Get a command binding from the command line or interactively */
nbind_p getname( void) ;
int tgetc( void) ; int tgetc( void) ;
int get1key( void) ; int get1key( void) ;
int getcmd( void) ; int getcmd( void) ;
int getstring( const char *prompt, char *buf, int nbuf, int eolchar) ; int getstring( const char *prompt, char *buf, int nbuf, int eolchar) ;
void ostring( char *s) ;
#endif #endif
/* end of input.h */

41
isa.h
View File

@ -1,41 +0,0 @@
/* isa.h -- isletter, islower, isupper, flipcase */
#ifndef __ISA_H__
#define __ISA_H__
#ifdef islower
# undef islower
#endif
#ifdef isupper
# undef isupper
#endif
#define NATIONL 0 /* if 1, interpret [,],\,{,},| as characters P.K. */
#if NATIONL
# define LASTUL ']'
# define LASTLL '}'
#else
# define LASTUL 'Z'
# define LASTLL 'z'
#endif
#define isletter(c) __isxletter((0xFF & (c)))
#define islower(c) isxlower((0xFF & (c)))
#define isupper(c) isxupper((0xFF & (c)))
#define __isxletter(c) (('a' <= c && LASTLL >= c) || \
('A' <= c && LASTUL >= c) || (192<=c /* && c<=255 */))
#define isxlower(c) (('a' <= c && LASTLL >= c) || (224 <= c && 252 >= c))
#define isxupper(c) (('A' <= c && LASTUL >= c) || (192 <= c && 220 >= c))
/* DIFCASE represents the integer difference between upper and lower
case letters. It is an xor-able value, which is fortunate, since the
relative positions of upper to lower case letters is the opposite of
ascii in ebcdic.
*/
#define DIFCASE 0x20 /* ASCII 'a' - 'A' */
#define flipcase( c) ((c) ^ DIFCASE) /* Toggle the case of a letter. */
#endif
/* end of isa.h */

View File

@ -1,7 +1,8 @@
/* isearch.c -- implements isearch.h */
#include "isearch.h" #include "isearch.h"
/* The functions in this file implement commands that perform incremental /* isearch.c
*
* The functions in this file implement commands that perform incremental
* searches in the forward and backward directions. This "ISearch" command * searches in the forward and backward directions. This "ISearch" command
* is intended to emulate the same command from the original EMACS * is intended to emulate the same command from the original EMACS
* implementation (ITS). Contains references to routines internal to * implementation (ITS). Contains references to routines internal to
@ -23,23 +24,25 @@
* Modified by Petri Kutvonen * Modified by Petri Kutvonen
*/ */
#include <stdio.h>
#include <string.h> #include <string.h>
#include "basic.h" #include "basic.h"
#include "buffer.h" #include "buffer.h"
#include "defines.h"
#include "display.h" #include "display.h"
#include "estruct.h"
#include "exec.h" #include "exec.h"
#include "input.h" #include "input.h"
#include "line.h" #include "line.h"
#include "search.h" #include "search.h"
#include "terminal.h" #include "terminal.h"
#include "util.h"
#include "window.h" #include "window.h"
/* /*
* Incremental search defines. * Incremental search defines.
*/ */
#if ISRCH
#define CMDBUFLEN 256 /* Length of our command buffer */ #define CMDBUFLEN 256 /* Length of our command buffer */
#define IS_ABORT 0x07 /* Abort the isearch */ #define IS_ABORT 0x07 /* Abort the isearch */
@ -56,7 +59,10 @@
/* IS_QUIT is no longer used, the variable metac is used instead */ /* IS_QUIT is no longer used, the variable metac is used instead */
static BINDABLE( isearch) ; /* internal use, not to be bound */ #endif
static int isearch( int f, int n) ;
static int checknext( char chr, char *patrn, int dir) ; static int checknext( char chr, char *patrn, int dir) ;
static int scanmore( char *patrn, int dir) ; static int scanmore( char *patrn, int dir) ;
static int match_pat( char *patrn) ; static int match_pat( char *patrn) ;
@ -66,6 +72,8 @@ static int uneat( void) ;
static void reeat( int c) ; static void reeat( int c) ;
#if ISRCH
static int echo_char(int c, int col); static int echo_char(int c, int col);
/* A couple of "own" variables for re-eat */ /* A couple of "own" variables for re-eat */
@ -80,10 +88,12 @@ static int cmd_offset; /* Current offset into command buff */
static int cmd_reexecute = -1; /* > 0 if re-executing command */ static int cmd_reexecute = -1; /* > 0 if re-executing command */
/* Subroutine to do incremental reverse search. It actually uses the /*
* Subroutine to do incremental reverse search. It actually uses the
* same code as the normal incremental search, as both can go both ways. * same code as the normal incremental search, as both can go both ways.
*/ */
BINDABLE( risearch) { int risearch(int f, int n)
{
struct line *curline; /* Current line on entry */ struct line *curline; /* Current line on entry */
int curoff; /* Current offset on entry */ int curoff; /* Current offset on entry */
@ -113,10 +123,11 @@ BINDABLE( risearch) {
return TRUE; return TRUE;
} }
/*
/* Again, but for the forward direction * Again, but for the forward direction
*/ */
BINDABLE( fisearch) { int fisearch(int f, int n)
{
struct line *curline; /* Current line on entry */ struct line *curline; /* Current line on entry */
int curoff; /* Current offset on entry */ int curoff; /* Current offset on entry */
@ -144,8 +155,8 @@ BINDABLE( fisearch) {
return TRUE; return TRUE;
} }
/*
/* Subroutine to do an incremental search. In general, this works similarly * Subroutine to do an incremental search. In general, this works similarly
* to the older micro-emacs search function, except that the search happens * to the older micro-emacs search function, except that the search happens
* as each character is typed, with the screen and cursor updated with each * as each character is typed, with the screen and cursor updated with each
* new search character. * new search character.
@ -170,7 +181,8 @@ BINDABLE( fisearch) {
* exists (or until the search is aborted). * exists (or until the search is aborted).
*/ */
static BINDABLE( isearch) { static int isearch(int f, int n)
{
int status; /* Search status */ int status; /* Search status */
int col; /* prompt column */ int col; /* prompt column */
unsigned cpos ; /* character number in search string */ unsigned cpos ; /* character number in search string */
@ -186,7 +198,8 @@ static BINDABLE( isearch) {
cmd_reexecute = -1; /* We're not re-executing (yet?) */ cmd_reexecute = -1; /* We're not re-executing (yet?) */
cmd_offset = 0; /* Start at the beginning of the buff */ cmd_offset = 0; /* Start at the beginning of the buff */
cmd_buff[0] = '\0'; /* Init the command buffer */ cmd_buff[0] = '\0'; /* Init the command buffer */
mystrscpy( pat_save, pat, sizeof pat_save) ; /* Save the old pattern string */ strncpy( pat_save, pat, sizeof pat_save - 1) ; /* Save the old pattern string */
pat_save[ sizeof pat_save - 1] = '\0' ;
curline = curwp->w_dotp; /* Save the current line pointer */ curline = curwp->w_dotp; /* Save the current line pointer */
curoff = curwp->w_doto; /* Save the current offset */ curoff = curwp->w_doto; /* Save the current offset */
init_direction = n; /* Save the initial search direction */ init_direction = n; /* Save the initial search direction */
@ -264,7 +277,7 @@ static BINDABLE( isearch) {
curwp->w_dotp = curline; /* Reset the line pointer */ curwp->w_dotp = curline; /* Reset the line pointer */
curwp->w_doto = curoff; /* and the offset */ curwp->w_doto = curoff; /* and the offset */
n = init_direction; /* Reset the search direction */ n = init_direction; /* Reset the search direction */
mystrscpy( pat, pat_save, sizeof pat) ; /* Restore the old search str */ strncpy( pat, pat_save, sizeof pat) ; /* Restore the old search str */
cmd_reexecute = 0; /* Start the whole mess over */ cmd_reexecute = 0; /* Start the whole mess over */
goto start_over; /* Let it take care of itself */ goto start_over; /* Let it take care of itself */
@ -528,6 +541,8 @@ static void reeat(int c)
saved_get_char = term.t_getchar; /* Save the char get routine */ saved_get_char = term.t_getchar; /* Save the char get routine */
term.t_getchar = uneat; /* Replace it with ours */ term.t_getchar = uneat; /* Replace it with ours */
} }
#else
int isearch(int f, int n)
/* end of isearch.c */ {
}
#endif

View File

@ -1,11 +1,11 @@
/* isearch.h -- incremental search */
#ifndef __ISEARCH_H__ #ifndef __ISEARCH_H__
#define __ISEARCH_H__ #define __ISEARCH_H__
#include "names.h" /* BINDABLE */ #define ISRCH 1 /* Incremental searches like ITS EMACS */
BINDABLE( risearch) ; #if ISRCH
BINDABLE( fisearch) ; int risearch( int f, int n) ;
int fisearch( int f, int n) ;
#endif
#endif #endif
/* end of isearch */

1368
line.c

File diff suppressed because it is too large Load Diff

76
line.h
View File

@ -1,25 +1,26 @@
/* line.h -- line centric interface */ #ifndef LINE_H_
#ifndef _LINE_H_ #define LINE_H_
#define _LINE_H_
#include "names.h" #include "retcode.h"
#include "utf8.h" #include "utf8.h"
/* All text is kept in circularly linked lists of "struct line" structures. #define NLINE 256 /* # of bytes, input line */
These begin at the header line (which is the blank line beyond the end
of the buffer). This line is pointed to by the "struct buffer". Each /*
line contains a number of bytes in the line (the "used" size), the size * All text is kept in circularly linked lists of "struct line" structures. These
of the text array, and the text. The end of line is not stored as a * begin at the header line (which is the blank line beyond the end of the
byte; it's implied. Future additions will include update hints, and a * buffer). This line is pointed to by the "struct buffer". Each line contains a the
list of marks into the line. * number of bytes in the line (the "used" size), the size of the text array,
* and the text. The end of line is not stored as a byte; it's implied. Future
* additions will include update hints, and a list of marks into the line.
*/ */
typedef struct line { struct line {
struct line *l_fp ; /* Forward link to the next line */ struct line *l_fp; /* Link to the next line */
struct line *l_bp ; /* Backward link to the previous line */ struct line *l_bp; /* Link to the previous line */
int l_size ; /* Allocated size */ int l_size; /* Allocated size */
int l_used ; /* Used size */ int l_used; /* Used size */
char l_text[] ; /* A bunch of characters */ char l_text[1]; /* A bunch of characters. */
} *line_p ; };
#define lforw(lp) ((lp)->l_fp) #define lforw(lp) ((lp)->l_fp)
#define lback(lp) ((lp)->l_bp) #define lback(lp) ((lp)->l_bp)
@ -27,30 +28,29 @@ typedef struct line {
#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c)) #define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
#define llength(lp) ((lp)->l_used) #define llength(lp) ((lp)->l_used)
extern int tabwidth ; /* Map to $tab, default to 8, can be set to [1, .. */ extern int tabmask ;
/* Bindable functions */ char *getkill( void) ;
BBINDABLE( backchar) ;
BBINDABLE( forwchar) ;
BINDABLE( insspace) ;
BINDABLE( yank) ;
int backchar( int f, int n) ;
int forwchar( int f, int n) ;
void lfree( struct line *lp) ;
void lchange( int flag) ; void lchange( int flag) ;
boolean linstr( char *instr) ; int insspace( int f, int n) ;
boolean linsert( int n, unicode_t c) ; int linstr( char *instr) ;
boolean linsert_byte( int n, int c) ; int linsert( int n, unicode_t c) ;
boolean lover( char *ostr) ; int lover( char *ostr) ;
boolean lnewline( void) ; int lnewline( void) ;
boolean ldelete( long n, boolean kflag) ; int ldelete( long n, int kflag) ;
boolean ldelchar( long n, boolean kflag) ; int ldelchar( long n, int kflag) ;
int lgetchar( unicode_t *cref) ; int lgetchar( unicode_t *) ;
char *getctext( void) ;
void kdelete( void) ; void kdelete( void) ;
int kinsert( int c) ; int kinsert( int c) ;
line_p lalloc( int minsize) ; /* Allocate a line of at least minsize chars. */ int yank( int f, int n) ;
void lfree( line_p lp) ; /* free a line, updating buffers and windows */ struct line *lalloc( int) ; /* Allocate a line. */
const char *getkill( void) ; /* get value of $kill */
boolean rdonly( void) ; /* Read Only error message */ boolean rdonly( void) ; /* Read Only error message */
#endif #endif /* LINE_H_ */
/* end of line.h */

16
list.c
View File

@ -1,16 +0,0 @@
/* 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
View File

@ -1,13 +0,0 @@
/* 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 */

11
lock.c
View File

@ -1,4 +1,4 @@
/* lock.c -- implements lock.h */ #include "estruct.h"
#include "lock.h" #include "lock.h"
/* LOCK.C /* LOCK.C
@ -22,11 +22,7 @@
#include "pklock.h" #include "pklock.h"
#endif #endif
#if BSD
#include <errno.h>
#else
#include <sys/errno.h> #include <sys/errno.h>
#endif
#define NLOCKS 100 /* max # of file locks active */ #define NLOCKS 100 /* max # of file locks active */
static char *lname[ NLOCKS] ; /* names of all locked files */ static char *lname[ NLOCKS] ; /* names of all locked files */
@ -171,9 +167,4 @@ void lckerror(char *errstr)
strcat(obuf, strerror(errno)); strcat(obuf, strerror(errno));
mlwrite(obuf); mlwrite(obuf);
} }
#else
typedef void _pedantic_empty_translation_unit ;
#endif #endif
/* end of lock.c */

11
lock.h
View File

@ -1,15 +1,16 @@
/* lock.h -- */
#ifndef _LOCK_H_ #ifndef _LOCK_H_
#define _LOCK_H_ #define _LOCK_H_
#include "defines.h" /* BSD, SVR4 */ #ifndef _ESTRUCT_H_
#error uEmacs compilation settings needs to be done!
#endif
#if BSD | SVR4
#if BSD | SVR4
int lockchk( const char *fname) ; int lockchk( const char *fname) ;
int lockrel( void) ; int lockrel( void) ;
int lock( const char *fname) ; int lock( const char *fname) ;
int unlock( const char *fname) ; int unlock( const char *fname) ;
#endif
#endif #endif
/* end of lock.h */ #endif

390
main.c
View File

@ -1,6 +1,11 @@
/* main.c -- */ /* main.c -- */
/* µEMACS 4.2 #define CLRMSG 0 /* space clears the message line with no insert */
/*
* main.c
*
* µEMACS 4.2
* *
* Based on: * Based on:
* *
@ -66,10 +71,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "defines.h" /* OS specific customization */ #include "estruct.h" /* Global structures and defines. */
#if UNIX #if UNIX
# include <signal.h> #include <signal.h>
# include <unistd.h>
#endif #endif
#include "basic.h" #include "basic.h"
@ -80,19 +84,29 @@
#include "eval.h" #include "eval.h"
#include "execute.h" #include "execute.h"
#include "file.h" #include "file.h"
#include "input.h"
#include "lock.h" #include "lock.h"
#include "mlout.h" #include "mlout.h"
#include "random.h" #include "random.h"
#include "search.h" #include "search.h"
#include "terminal.h" #include "terminal.h"
#include "termio.h" #include "termio.h"
#include "util.h"
#include "version.h" #include "version.h"
#include "window.h" #include "window.h"
/* For MSDOS, increase the default stack space. */
#if MSDOS & TURBO
#if PKCODE
extern unsigned _stklen = 20000;
#else
extern unsigned _stklen = 32766;
#endif
#endif
#if UNIX #if UNIX
static void emergencyexit( int signr) { static void emergencyexit(int signr)
quickexit( FALSE, 0) ; {
quickexit(FALSE, 0);
quit( TRUE, 0) ; /* If quickexit fails (to save changes), do a force quit */ quit( TRUE, 0) ; /* If quickexit fails (to save changes), do a force quit */
} }
#endif #endif
@ -100,46 +114,70 @@ static void emergencyexit( int signr) {
static void edinit( char *bname) ; static void edinit( char *bname) ;
static void version( void) { static void version( void) {
fputs( PROGRAM_NAME_UTF8 " version " VERSION "\n", stdout) ; fputs( PROGRAM_NAME_PFX PROGRAM_NAME_LONG " version " VERSION "\n", stdout) ;
} }
static void usage( void) { static void usage( void) {
fputs( "Usage: " PROGRAM_NAME " [OPTION|FILE]..\n\n" fputs( "Usage: " PROGRAM_NAME " [OPTION].. [FILE]..\n\n"
" + start at the end of file\n" " + start at the end of file\n"
" +<n> start at line <n>\n" " +<n> start at line <n>\n"
" --help display this help and exit\n" " --help display this help and exit\n"
" --version output version information and exit\n" " --version output version information and exit\n"
" @cmdfile execute startup file\n"
" -a|A process error file\n" " -a|A process error file\n"
" -e|E edit file\n" " -e|E edit file\n"
" -g|G<n> go to line <n>\n" " -g|G<n> go to line <n>\n"
#if CRYPT
" -k|K<key> use code key\n"
#endif
" -r|R restrictive use\n" " -r|R restrictive use\n"
" -s|S<string> search string\n" " -s|S<string> search string\n"
" -v|V view file\n" " -v|V view file\n"
" -x|Xcmdfile\n" " -x|Xcmdfile\n"
" -x|X cmdfile execute command file\n" " -x|X cmdfile execute command file\n"
" @cmdfile execute startup file\n"
, stdout) ; , stdout) ;
} }
int main( int argc, char *argv[]) { int main(int argc, char **argv)
buffer_p bp; /* temp buffer pointer */ {
int c = -1; /* command character */
int f; /* default flag */
int n; /* numeric repeat count */
int mflag; /* negative flag on repeat */
struct buffer *bp; /* temp buffer pointer */
int firstfile; /* first file flag */ int firstfile; /* first file flag */
int carg; /* current arg to scan */ int carg; /* current arg to scan */
int startflag; /* startup executed flag */ int startflag; /* startup executed flag */
buffer_p firstbp = NULL; /* ptr to first buffer in cmd line */ struct buffer *firstbp = NULL; /* ptr to first buffer in cmd line */
int basec; /* c stripped of meta character */
int viewflag; /* are we starting in view mode? */ int viewflag; /* are we starting in view mode? */
int gotoflag; /* do we need to goto a line at start? */ int gotoflag; /* do we need to goto a line at start? */
int gline = 0; /* if so, what line? */ int gline = 0; /* if so, what line? */
int searchflag; /* Do we need to search at start? */ int searchflag; /* Do we need to search at start? */
int saveflag; /* temp store for lastflag */
int errflag; /* C error processing? */ int errflag; /* C error processing? */
bname_t bname ; /* buffer name of file to read */ bname_t bname ; /* buffer name of file to read */
#if CRYPT
int cryptflag; /* encrypting on the way in? */
ekey_t ekey ; /* startup encryption key */
#endif
int newc;
#if PKCODE & VMS
(void) umask(-1); /* Use old protection (this is at wrong place). */
#endif
#if PKCODE & BSD #if PKCODE & BSD
sleep(1); /* Time for window manager. */ sleep(1); /* Time for window manager. */
#endif #endif
#if UNIX
#ifdef SIGWINCH
signal(SIGWINCH, sizesignal);
#endif
#endif
if( argc == 2) { if( argc == 2) {
if( strcmp( argv[ 1], "--help") == 0) { if( strcmp( argv[ 1], "--help") == 0) {
usage() ; usage() ;
@ -152,10 +190,11 @@ int main( int argc, char *argv[]) {
} }
} }
vtinit() ; /* Display */ /* Initialize the editor. */
vtinit(); /* Display */
mloutfmt = mlwrite ; mloutfmt = mlwrite ;
edinit( "main") ; /* Bindings, buffers, windows */ edinit("main"); /* Buffers, windows */
varinit() ; /* user variables */ varinit(); /* user variables */
viewflag = FALSE; /* view mode defaults off in command line */ viewflag = FALSE; /* view mode defaults off in command line */
gotoflag = FALSE; /* set to off to begin with */ gotoflag = FALSE; /* set to off to begin with */
@ -163,6 +202,9 @@ int main( int argc, char *argv[]) {
firstfile = TRUE; /* no file to edit yet */ firstfile = TRUE; /* no file to edit yet */
startflag = FALSE; /* startup file not executed yet */ startflag = FALSE; /* startup file not executed yet */
errflag = FALSE; /* not doing C error parsing */ errflag = FALSE; /* not doing C error parsing */
#if CRYPT
cryptflag = FALSE; /* no encryption by default */
#endif
/* Insure screen is initialized before startup and goto/search */ /* Insure screen is initialized before startup and goto/search */
update( FALSE) ; update( FALSE) ;
@ -192,6 +234,14 @@ int main( int argc, char *argv[]) {
gotoflag = TRUE; gotoflag = TRUE;
gline = atoi(&argv[carg][2]); gline = atoi(&argv[carg][2]);
break; break;
#if CRYPT
case 'k': /* -k<key> for code key */
case 'K':
cryptflag = TRUE;
strncpy( ekey, &argv[ carg][ 2], sizeof ekey - 1) ;
ekey[ sizeof ekey - 1] = 0 ;
break;
#endif
case 'r': /* -r restrictive use */ case 'r': /* -r restrictive use */
case 'R': case 'R':
restflag = TRUE; restflag = TRUE;
@ -199,7 +249,8 @@ int main( int argc, char *argv[]) {
case 's': /* -s for initial search string */ case 's': /* -s for initial search string */
case 'S': case 'S':
searchflag = TRUE; searchflag = TRUE;
mystrscpy( pat, &argv[ carg][ 2], sizeof pat) ; strncpy( pat, &argv[ carg][ 2], sizeof pat - 1) ;
pat[ sizeof pat -1] = 0 ;
break; break;
case 'v': /* -v for View File */ case 'v': /* -v for View File */
case 'V': case 'V':
@ -213,7 +264,7 @@ int main( int argc, char *argv[]) {
} else if( argv[ carg + 1]) { /* -X filename */ } else if( argv[ carg + 1]) { /* -X filename */
if( startup( &argv[ carg + 1][ 0]) == TRUE) if( startup( &argv[ carg + 1][ 0]) == TRUE)
startflag = TRUE ; /* don't execute emacs.rc */ startflag = TRUE ; /* don't execute emacs.rc */
carg += 1 ; carg += 1 ;
} }
@ -245,7 +296,8 @@ int main( int argc, char *argv[]) {
exit( EXIT_FAILURE) ; exit( EXIT_FAILURE) ;
} }
mystrscpy( bp->b_fname, argv[ carg], sizeof bp->b_fname) ; /* max filename length limited to NFILEN - 1 */ strncpy( bp->b_fname, argv[ carg], sizeof bp->b_fname - 1) ; /* max filename length limited to NFILEN - 1 (79) */
bp->b_fname[ sizeof bp->b_fname - 1] = 0 ;
bp->b_active = FALSE; bp->b_active = FALSE;
if (firstfile) { if (firstfile) {
firstbp = bp; firstbp = bp;
@ -255,6 +307,13 @@ int main( int argc, char *argv[]) {
/* set the modes appropriatly */ /* set the modes appropriatly */
if (viewflag) if (viewflag)
bp->b_mode |= MDVIEW; bp->b_mode |= MDVIEW;
#if CRYPT
if (cryptflag) {
bp->b_mode |= MDCRYPT;
strncpy( bp->b_key, ekey, sizeof ekey) ;
cryptbufferkey( bp) ;
}
#endif
} }
} }
@ -273,9 +332,10 @@ int main( int argc, char *argv[]) {
/* if invoked with no other startup files, /* if invoked with no other startup files,
run the system startup file here */ run the system startup file here */
if( (startflag == FALSE) && (startup( "") != TRUE)) if (startflag == FALSE) {
mloutstr( "Default startup failed!") ; startup("");
startflag = TRUE;
}
discmd = TRUE; /* P.K. */ discmd = TRUE; /* P.K. */
/* if there are any files to read, read the first one! */ /* if there are any files to read, read the first one! */
@ -304,24 +364,147 @@ int main( int argc, char *argv[]) {
if( forwhunt( FALSE, 0)) if( forwhunt( FALSE, 0))
mloutfmt( "Found on line %d", getcline()) ; mloutfmt( "Found on line %d", getcline()) ;
kbd_loop() ; /* Setup to process commands. */
return EXIT_SUCCESS ; /* never reached */ lastflag = 0; /* Fake last flags. */
}
loop:
/* Execute the "command" macro...normally null. */
saveflag = lastflag; /* Preserve lastflag through this. */
execute(META | SPEC | 'C', FALSE, 1);
lastflag = saveflag;
#if TYPEAH && PKCODE
if (typahead()) {
newc = getcmd();
update(FALSE);
do {
fn_t execfunc;
if (c == newc && (execfunc = getbind(c)) != NULL
&& execfunc != insert_newline
&& execfunc != insert_tab)
newc = getcmd();
else
break;
} while (typahead());
c = newc;
} else {
update(FALSE);
c = getcmd();
}
#else
/* Fix up the screen */
update(FALSE);
/* get the next command from the keyboard */
c = getcmd();
#endif
/* if there is something on the command line, clear it */
if (mpresf != FALSE) {
mloutstr( "") ;
update(FALSE);
#if CLRMSG
if (c == ' ') /* ITS EMACS does this */
goto loop;
#endif
}
f = FALSE;
n = 1;
/* do META-# processing if needed */
basec = c & ~META; /* strip meta char off if there */
if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) {
f = TRUE; /* there is a # arg */
n = 0; /* start with a zero default */
mflag = 1; /* current minus flag */
c = basec; /* strip the META */
while ((c >= '0' && c <= '9') || (c == '-')) {
if (c == '-') {
/* already hit a minus or digit? */
if ((mflag == -1) || (n != 0))
break;
mflag = -1;
} else {
n = n * 10 + (c - '0');
}
if ((n == 0) && (mflag == -1)) /* lonely - */
mloutstr( "Arg:") ;
else
mloutfmt( "Arg: %d", n * mflag) ;
c = getcmd(); /* get the next key */
}
n = n * mflag; /* figure in the sign */
}
/* do ^U repeat argument processing */
if (c == reptc) { /* ^U, start argument */
f = TRUE;
n = 4; /* with argument of 4 */
mflag = 0; /* that can be discarded. */
mloutstr( "Arg: 4") ;
while (((c = getcmd()) >= '0' && c <= '9') || c == reptc
|| c == '-') {
if (c == reptc)
if ((n > 0) == ((n * 4) > 0))
n = n * 4;
else
n = 1;
/*
* If dash, and start of argument string, set arg.
* to -1. Otherwise, insert it.
*/
else if (c == '-') {
if (mflag)
break;
n = 0;
mflag = -1;
}
/*
* If first digit entered, replace previous argument
* with digit and set sign. Otherwise, append to arg.
*/
else {
if (!mflag) {
n = 0;
mflag = 1;
}
n = 10 * n + c - '0';
}
mloutfmt( "Arg: %d", (mflag >= 0) ? n : (n ? -n : -1)) ;
}
/*
* Make arguments preceded by a minus sign negative and change
* the special argument "^U -" to an effective "^U -1".
*/
if (mflag == -1) {
if (n == 0)
n++;
n = -n;
}
}
/* and execute the command */
execute(c, f, n);
goto loop;
}
/* /*
* Initialize all of the buffers and windows. The buffer name is passed down * Initialize all of the buffers and windows. The buffer name is passed down
* as an argument, because the main routine may have been told to read in a * as an argument, because the main routine may have been told to read in a
* file by default, and we want the buffer name to be right. * file by default, and we want the buffer name to be right.
*/ */
static void edinit( char *bname) { static void edinit(char *bname)
buffer_p bp; {
window_p wp; struct buffer *bp;
struct window *wp;
if( !init_bindings() /* initialize mapping of function to name and key */ bp = bfind(bname, TRUE, 0); /* First buffer */
|| NULL == (bp = bfind( bname, TRUE, 0)) /* First buffer */ blistp = bfind("*List*", TRUE, BFINVS); /* Buffer list buffer */
|| NULL == (blistp = bfind( "*List*", TRUE, BFINVS)) /* Buffer list */ wp = (struct window *)malloc(sizeof(struct window)); /* First window */
|| NULL == (wp = malloc( sizeof *wp))) { /* First window */ if (bp == NULL || wp == NULL || blistp == NULL) {
fputs( "First initialisation failed!\n", stderr) ; fputs( "First initialisation failed!\n", stderr) ;
exit( EXIT_FAILURE) ; exit( EXIT_FAILURE) ;
} }
@ -348,109 +531,126 @@ static void edinit( char *bname) {
wp->w_flag = WFMODE | WFHARD; /* Full. */ wp->w_flag = WFMODE | WFHARD; /* Full. */
} }
/***** Compiler specific Library functions ****/ /***** Compiler specific Library functions ****/
#if RAMSIZE #if RAMSIZE
/* These routines will allow me to track memory usage by placing
a layer on top of the standard system malloc() and free() calls.
with this code defined, the environment variable, $RAM, will
report on the number of bytes allocated via malloc.
/* These routines will allow me to track memory usage by placing a layer on with SHOWRAM defined, the number is also posted on the
top of the standard system malloc() and free() calls. with this code end of the bottom mode line and is updated whenever it is changed.
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.
*/ */
#if RAMSHOW static void dspram( void) ;
static void dspram( void) ;
#endif
void *allocate( size_t nbytes) { #undef malloc
nbytes += sizeof nbytes ; /* add overhead to track allocation */ #undef free
size_t *mp = (malloc)( nbytes) ; /* call the function not the macro */ #if 0
if( mp) { char *allocate(nbytes)
*mp++ = nbytes ; /* allocate nbytes and track */
envram += nbytes ; unsigned nbytes; /* # of bytes to allocate */
#endif
void *allocate( size_t nbytes)
{
char *mp; /* ptr returned from malloc */
/* char *malloc(); */
mp = malloc(nbytes);
if (mp) {
envram += nbytes;
#if RAMSHOW #if RAMSHOW
dspram() ; dspram();
#endif #endif
} }
return mp ; return mp;
} }
void release( void *mp) { #if 0
if( mp) { release(mp)
size_t *sp = mp ; /* release malloced memory and track */
sp-- ; char *mp; /* chunk of RAM to release */
#endif
void release( void *mp)
{
unsigned *lp; /* ptr to the long containing the block size */
if (mp) {
/* update amount of ram currently malloced */ /* update amount of ram currently malloced */
envram -= *sp ; lp = ((unsigned *) mp) - 1;
(free)( sp) ; /* call the function not the macro */ envram -= (long) *lp - 2;
free(mp);
#if RAMSHOW #if RAMSHOW
dspram() ; dspram();
#endif #endif
} }
} }
#if RAMSHOW #if RAMSHOW
static void dspram( void) { /* display the amount of RAM currently malloced */ static void dspram( void)
char mbuf[ 20] ; { /* display the amount of RAM currently malloced */
char mbuf[20];
char *sp;
TTmove( term.t_nrow, term.t_ncol - 12) ; TTmove(term.t_nrow - 1, 70);
#if COLOR #if COLOR
TTforg( 7) ; TTforg(7);
TTbacg(0) ; TTbacg(0);
#endif #endif
sprintf( mbuf, "[%10u]", envram) ; sprintf(mbuf, "[%lu]", envram);
char *sp = mbuf ; sp = &mbuf[0];
while( *sp) while (*sp)
TTputc( *sp++) ; TTputc(*sp++);
TTmove(term.t_nrow, 0);
TTmove( term.t_nrow, 0) ; movecursor(term.t_nrow, 0);
movecursor( term.t_nrow, 0) ;
} }
#endif #endif
#endif #endif
/* On some primitive operation systems, and when emacs is used as /* On some primitave operation systems, and when emacs is used as
a subprogram to a larger project, emacs needs to de-alloc its a subprogram to a larger project, emacs needs to de-alloc its
own used memory own used memory
*/ */
#if CLEAN #if CLEAN
/* cexit() /*
* cexit()
* *
* int status; return status of emacs * int status; return status of emacs
*/ */
void cexit( int status) { void cexit( int status) {
/* first clean up the windows */ struct buffer *bp; /* buffer list pointer */
window_p wp = wheadp ; struct window *wp; /* window list pointer */
while( wp) { struct window *tp; /* temporary window pointer */
window_p tp = wp->w_wndp ;
free( wp) ;
wp = tp ;
}
wheadp = NULL ;
/* then the buffers */ /* first clean up the windows */
buffer_p bp ; wp = wheadp;
while( (bp = bheadp) != NULL) { while (wp) {
bp->b_nwnd = 0 ; tp = wp->w_wndp;
bp->b_flag = 0 ; /* don't say anything about a changed buffer! */ free(wp);
zotbuf( bp) ; wp = tp;
}
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;
} }
/* and the kill buffer */ /* and the kill buffer */
kdelete() ; kdelete();
/* and the video buffers */ /* and the video buffers */
vtfree() ; vtfree();
(exit)( status) ; /* call the function, not the macro */ #undef exit
exit(status);
} }
#endif #endif
/* end of main.c */

105
maze.cmd
View File

@ -1,105 +0,0 @@
## maze.cmd -- draw a block maze
# 5 set $seed
set %S $seed # record seed
# setup direction offsets
set %D1 0
set %D2 1
set %D3 0
set %D4 -1
set %D5 0
select-buffer maze
# draw the maze layout
$curwidth insert-string " "
newline
set %w &sub $curwidth 2
!if &equ 0 &mod %w 2
set %w &sub %w 1
!endif
insert-string " "
%w insert-string ""
insert-string " "
set %buf $line
set %l &sub $pagelen 4
!if &equ 1 &mod %l 2
set %l &sub %l 1
!endif
set %cnt %l
!while &less 0 %cnt
set %cnt &sub %cnt 1
newline
insert-string %buf
!endwhile
newline
set %w &add %w 1
%w insert-string " "
set %l &add %l 3
# draw the exit
set $curline &sub %l 2
set $curcol &sub %w 1
set $curchar 32
# draw the maze
set %x 2
set %y 3
set $curline %y
set $curcol %x
set $curchar 32
set %flags 0
set %cnt &tim &sub &div %w 2 1 &sub &div %l 2 1
!while &les 1 %cnt
!if &or &equ %flags 15 &not &equ $curchar 32
set %flags 0
set %y &add %y 2
!if &equ %y %l
set %y 3
set %x &add %x 2
!if &equ %x %w
set %x 2
!endif
!endif
!else
set %D &rnd 4
set %OX &ind &cat "%D" %D
set %OY &ind &cat "%D" &add %D 1
set $curline &add %y &tim 2 %OY
set %i &add %x &tim 2 %OX
set $curcol %i
!if &equ $curchar 32
!if &equ %D 3 # turn direction into bitmask {1,2,4,8}
set %D 8
!endif
set %flags &bor %flags %D # mark direction as checked
!else
set $curchar 32
set %y $curline # update current position
set %x %i
set $curline &sub %y %OY # erase path between old and cur pos
set $curcol &sub %x %OX
set $curchar 32
set %flags 0
set %cnt &sub %cnt 1
update-screen
!endif
!endif
set $curline %y
set $curcol %x
!endwhile
# id maze
beginning-of-file
kill-to-end-of-line
insert-string &cat " Maze " &cat %w &cat "x" &cat &sub %l 2 &cat " #" %S
write-message $line
&sub $curwidth $curcol insert-string " "
# draw the entrance
set $curline 3
set $curcol 1
set $curchar 32
unmark-buffer

191
mingw32.c Normal file
View File

@ -0,0 +1,191 @@
#ifdef MINGW32
#include "termio.h"
#include "terminal.h"
#include <errno.h>
#include <io.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include "utf8.h"
#include "wscreen.h"
static void vv( void) {}
static void vi( int i) {}
static int is( char *s) { return *s ; }
static void ttmove( int l, int c) ;
#define MARGIN 8
#define SCRSIZ 64
#define NPAUSE 10 /* # times thru update to pause. */
struct terminal term = {
24, /* These four values are set dynamically at open time. */
24,
80,
80,
MARGIN,
SCRSIZ,
NPAUSE,
ttopen,
#if PKCODE
ttclose,
#else
ttclose,
#endif
vv, /* ttkopen, */
vv, /* ttkclose, */
ttgetc,
ttputc,
ttflush,
ttmove,
vv, /* tteeol, */
vv, /* tteeop, */
vv, /* ttbeep, */
vi, /* ttrev, */
is /* ttcres */
#if COLOR
, iv, /* ttfcol, */
iv /* ttbcol */
#endif
#if SCROLLCODE
, NULL /* set dynamically at open time */
#endif
} ;
int ttrow ; /* Row location of HW cursor */
int ttcol ; /* Column location of HW cursor */
boolean eolexist = TRUE ; /* does clear to EOL exist? */
boolean revexist = FALSE ; /* does reverse video exist? */
boolean sgarbf = TRUE ; /* State of screen unknown */
char sres[ 16] ; /* Current screen resolution. */
/* NORMAL, CGA, EGA, VGA */
void ttopen( void) {
winit() ;
wcls() ;
term.t_mrow = term.t_nrow = wbottom() - wtop() ;
term.t_mcol = term.t_ncol = wright() - wleft() + 1 ;
wtitle( "uEMACS") ;
}
void ttclose( void) {
}
int ttputc( int c) {
char utf8[ 6] ;
int bytes ;
bytes = unicode_to_utf8( c, utf8) ;
fwrite( utf8, 1, bytes, stdout);
return 0 ;
}
void ttflush( void) {
int status ;
status = fflush( stdout);
while( status < 0 && errno == EAGAIN) {
_sleep( 1) ;
status = fflush( stdout) ;
}
if( status < 0)
exit( 15) ;
}
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 ;
}
c = (unsigned char) buffer[ 0] ;
if( c >= 32 && c < 128)
goto done ;
/*
* Lazy. We don't bother calculating the exact
* expected length. We want at least two characters
* for the special character case (ESC+[) and for
* the normal short UTF8 sequence that starts with
* the 110xxxxx pattern.
*
* But if we have any of the other patterns, just
* try to get more characters. At worst, that will
* just result in a barely perceptible 0.1 second
* delay for some *very* unusual utf8 character
* input.
*/
expected = 2 ;
if( (c & 0xe0) == 0xe0)
expected = 6 ;
/* Special character - try to fill buffer */
if( count < expected) {
int n;
#if 0
ntermios.c_cc[VMIN] = 0;
ntermios.c_cc[VTIME] = 1; /* A .1 second lag */
tcsetattr(0, TCSANOW, &ntermios);
#endif
n = read(0, buffer + count, sizeof(buffer) - count);
/* Undo timeout */
#if 0
ntermios.c_cc[VMIN] = 1;
ntermios.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &ntermios);
#endif
if (n > 0)
pending += n;
}
if( pending > 1) {
unsigned char second = buffer[1];
/* Turn ESC+'[' into CSI */
if (c == 27 && second == '[') {
bytes = 2;
c = 128+27;
goto done;
}
}
bytes = utf8_to_unicode( buffer, 0, pending, &c) ;
done:
pending -= bytes ;
memmove( buffer, buffer+bytes, pending) ;
return c ;
}
int typahead( void) {
int x ; /* holds # of pending chars */
#ifdef FIONREAD
if( ioctl( 0, FIONREAD, &x) < 0)
#endif
x = 0 ;
return x ;
}
static void ttmove( int l, int c) {
wgoxy( c, l) ;
}
#endif

View File

@ -12,9 +12,4 @@ void mloutstr( const char *str) {
mloutfmt( (*str) ? "%s" : "", str) ; mloutfmt( (*str) ? "%s" : "", str) ;
} }
boolean mloutfail( const char *msg) {
mloutfmt( "%B%s", msg) ;
return FALSE ;
}
/* end of mlout.c */ /* end of mlout.c */

View File

@ -1,13 +1,12 @@
/* mlout.h -- message line output interface */ /* mlout.h -- message line output interface */
#ifndef __MLOUT_H__ #ifndef __MLOUT_H__
#define __MLOUT_H__ #define __MLOUT_H__
#include "retcode.h"
extern void (*mloutfmt)( const char *, ...) ; extern void (*mloutfmt)( const char *, ...) ;
void mloutstr( const char *str) ; void mloutstr( const char *str) ;
boolean mloutfail( const char *msg) ; /* output with BELL and return FALSE */
#endif #endif /* __MLOUT_H__ */
/* end of mlout.h */ /* end of mlout.h */

616
names.c
View File

@ -3,24 +3,20 @@
/* Name to function binding table. /* Name to function binding table.
* *
* This table gives the names of all the bindable functions and their C * This table gives the names of all the bindable functions
* function address. These are used for the bind-to-key function and * and their C function address. These are used for the bind-to-key
* command line parsing. * function.
*/ */
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "basic.h" #include "basic.h"
#include "bind.h" #include "bind.h"
#include "bindable.h" #include "bindable.h"
#include "buffer.h" #include "buffer.h"
#include "defines.h" /* malloc/allocate */
#include "display.h" #include "display.h"
#include "eval.h" #include "eval.h"
#include "exec.h" #include "exec.h"
#include "execute.h"
#include "file.h" #include "file.h"
#include "isearch.h" #include "isearch.h"
#include "line.h" #include "line.h"
@ -28,415 +24,215 @@
#include "random.h" #include "random.h"
#include "search.h" #include "search.h"
#include "spawn.h" #include "spawn.h"
#include "util.h"
#include "window.h" #include "window.h"
#include "word.h" #include "word.h"
struct name_bind names[] = {
const name_bind names[] = { {"abort-command", ctrlg},
{" abort-command", ctrlg, CTL_ | 'G'} , {"add-mode", setemode},
{" add-global-mode", setgmode, META | 'M'} , {"add-global-mode", setgmode},
{" add-mode", setemode, CTLX | 'M'} , #if APROP
{" apropos", apro, META | 'A'} , {"apropos", apro},
{" backward-character", (fnp_t) backchar, CTL_ | 'B'} , #endif
{" begin-macro", (fnp_t) ctlxlp, CTLX | '('} , {"backward-character", backchar},
{" beginning-of-file", (fnp_t) gotobob, META | '<'} , {"begin-macro", ctlxlp},
{" beginning-of-line", (fnp_t) gotobol, CTL_ | 'A'} , {"beginning-of-file", gotobob},
{" bind-to-key", bindtokey, META | 'K'} , {"beginning-of-line", gotobol},
{" buffer-position", showcpos, CTLX | '='} , {"bind-to-key", bindtokey},
{"!case-region-lower", lowerregion, CTLX | CTL_ | 'L'} , {"buffer-position", showcpos},
{"!case-region-upper", upperregion, CTLX | CTL_ | 'U'} , {"case-region-lower", lowerregion},
{"!case-word-capitalize", capword, META | 'C'} , {"case-region-upper", upperregion},
{"!case-word-lower", lowerword, META | 'L'} , {"case-word-capitalize", capword},
{"!case-word-upper", upperword, META | 'U'} , {"case-word-lower", lowerword},
{" change-file-name", filename, CTLX | 'N'} , {"case-word-upper", upperword},
{" change-screen-size", (fnp_t) newsize, META | CTL_ | 'D'} , /* M^S */ {"change-file-name", filename},
{" change-screen-width", (fnp_t) newwidth, META | CTL_ | 'T'} , {"change-screen-size", newsize},
{" clear-and-redraw", (fnp_t) redraw, CTL_ | 'L'} , {"change-screen-width", newwidth},
{" clear-message-line", (fnp_t) clrmes, 0} , {"clear-and-redraw", redraw},
{" copy-region", copyregion, META | 'W'} , {"clear-message-line", clrmes},
{" count-words", wordcount, META | CTL_ | 'C'} , {"copy-region", copyregion},
{" ctlx-prefix", (fnp_t) cex, CTL_ | 'X'} , #if WORDPRO
{"!delete-blank-lines", deblank, CTLX | CTL_ | 'O'} , {"count-words", wordcount},
{" delete-buffer", killbuffer, CTLX | 'K'} , #endif
{" delete-global-mode", delgmode, META | CTL_ | 'M'} , {"ctlx-prefix", cex},
{" delete-mode", delmode, CTLX | CTL_ | 'M'} , {"delete-blank-lines", deblank},
{"!delete-next-character", forwdel, CTL_ | 'D'} , {"delete-buffer", killbuffer},
{"!delete-next-word", delfword, META | 'D'} , {"delete-mode", delmode},
{" delete-other-windows", onlywind, CTLX | '1'} , {"delete-global-mode", delgmode},
{"!delete-previous-character", backdel, CTL_ | 'H'} , /* ^? */ {"delete-next-character", forwdel},
{"!delete-previous-word", delbword, META | CTL_ | 'H'} , /* M^? */ {"delete-next-word", delfword},
{" delete-window", delwind, CTLX | '0'} , {"delete-other-windows", onlywind},
{" describe-bindings", desbind, 0} , {"delete-previous-character", backdel},
{" describe-key", deskey, CTLX | '?'} , {"delete-previous-word", delbword},
{"!detab-line", detab, CTLX | CTL_ | 'D'} , /* X^A */ {"delete-window", delwind},
{" end-macro", (fnp_t) ctlxrp, CTLX | ')'} , {"describe-bindings", desbind},
{" end-of-file", (fnp_t) gotoeob, META | '>'} , {"describe-key", deskey},
{" end-of-line", (fnp_t) gotoeol, CTL_ | 'E'} , #if AEDIT
{"!entab-line", entab, CTLX | CTL_ | 'E'} , {"detab-line", detab},
{" exchange-point-and-mark", (fnp_t) swapmark, CTLX | CTL_ | 'X'} , #endif
{" execute-buffer", execbuf, 0} , {"end-macro", ctlxrp},
{" execute-command-line", execcmd, 0} , {"end-of-file", gotoeob},
{" execute-file", execfile, 0} , {"end-of-line", gotoeol},
{" execute-macro", (fnp_t) ctlxe, CTLX | 'E'} , #if AEDIT
{" execute-macro-1", cbuf1, 0} , {"entab-line", entab},
{" execute-macro-10", cbuf10, 0} , #endif
{" execute-macro-11", cbuf11, 0} , {"exchange-point-and-mark", swapmark},
{" execute-macro-12", cbuf12, 0} , {"execute-buffer", execbuf},
{" execute-macro-13", cbuf13, 0} , {"execute-command-line", execcmd},
{" execute-macro-14", cbuf14, 0} , {"execute-file", execfile},
{" execute-macro-15", cbuf15, 0} , {"execute-macro", ctlxe},
{" execute-macro-16", cbuf16, 0} , {"execute-macro-1", cbuf1},
{" execute-macro-17", cbuf17, 0} , {"execute-macro-2", cbuf2},
{" execute-macro-18", cbuf18, 0} , {"execute-macro-3", cbuf3},
{" execute-macro-19", cbuf19, 0} , {"execute-macro-4", cbuf4},
{" execute-macro-2", cbuf2, 0} , {"execute-macro-5", cbuf5},
{" execute-macro-20", cbuf20, 0} , {"execute-macro-6", cbuf6},
{" execute-macro-21", cbuf21, 0} , {"execute-macro-7", cbuf7},
{" execute-macro-22", cbuf22, 0} , {"execute-macro-8", cbuf8},
{" execute-macro-23", cbuf23, 0} , {"execute-macro-9", cbuf9},
{" execute-macro-24", cbuf24, 0} , {"execute-macro-10", cbuf10},
{" execute-macro-25", cbuf25, 0} , {"execute-macro-11", cbuf11},
{" execute-macro-26", cbuf26, 0} , {"execute-macro-12", cbuf12},
{" execute-macro-27", cbuf27, 0} , {"execute-macro-13", cbuf13},
{" execute-macro-28", cbuf28, 0} , {"execute-macro-14", cbuf14},
{" execute-macro-29", cbuf29, 0} , {"execute-macro-15", cbuf15},
{" execute-macro-3", cbuf3, 0} , {"execute-macro-16", cbuf16},
{" execute-macro-30", cbuf30, 0} , {"execute-macro-17", cbuf17},
{" execute-macro-31", cbuf31, 0} , {"execute-macro-18", cbuf18},
{" execute-macro-32", cbuf32, 0} , {"execute-macro-19", cbuf19},
{" execute-macro-33", cbuf33, 0} , {"execute-macro-20", cbuf20},
{" execute-macro-34", cbuf34, 0} , {"execute-macro-21", cbuf21},
{" execute-macro-35", cbuf35, 0} , {"execute-macro-22", cbuf22},
{" execute-macro-36", cbuf36, 0} , {"execute-macro-23", cbuf23},
{" execute-macro-37", cbuf37, 0} , {"execute-macro-24", cbuf24},
{" execute-macro-38", cbuf38, 0} , {"execute-macro-25", cbuf25},
{" execute-macro-39", cbuf39, 0} , {"execute-macro-26", cbuf26},
{" execute-macro-4", cbuf4, 0} , {"execute-macro-27", cbuf27},
{" execute-macro-40", cbuf40, 0} , {"execute-macro-28", cbuf28},
{" execute-macro-5", cbuf5, 0} , {"execute-macro-29", cbuf29},
{" execute-macro-6", cbuf6, 0} , {"execute-macro-30", cbuf30},
{" execute-macro-7", cbuf7, 0} , {"execute-macro-31", cbuf31},
{" execute-macro-8", cbuf8, 0} , {"execute-macro-32", cbuf32},
{" execute-macro-9", cbuf9, 0} , {"execute-macro-33", cbuf33},
{" execute-named-command", namedcmd, META | 'X'} , {"execute-macro-34", cbuf34},
{" execute-procedure", execproc, META | CTL_ | 'E'} , {"execute-macro-35", cbuf35},
{" execute-program", execprg, CTLX | '$'} , {"execute-macro-36", cbuf36},
{" exit-emacs", quit, CTLX | CTL_ | 'C'} , {"execute-macro-37", cbuf37},
{"!fill-paragraph", fillpara, META | 'Q'} , {"execute-macro-38", cbuf38},
{"!filter-buffer", filter_buffer, CTLX | '#'} , {"execute-macro-39", cbuf39},
{" find-file", filefind, CTLX | CTL_ | 'F'} , {"execute-macro-40", cbuf40},
{" forward-character", (fnp_t) forwchar, CTL_ | 'F'} , {"execute-named-command", namedcmd},
{" goto-line", gotoline, META | 'G'} , #if PROC
{"execute-procedure", execproc},
#endif
{"execute-program", execprg},
{"exit-emacs", quit},
#if WORDPRO
{"fill-paragraph", fillpara},
#endif
{"filter-buffer", filter_buffer},
{"find-file", filefind},
{"forward-character", forwchar},
{"goto-line", gotoline},
#if CFENCE #if CFENCE
{" goto-matching-fence", getfence, META | CTL_ | 'F'} , {"goto-matching-fence", getfence},
#endif #endif
{" grow-window", enlargewind, CTLX | 'Z'} , /* X^ */ {"grow-window", enlargewind},
{"!handle-tab", insert_tab, CTL_ | 'I'} , {"handle-tab", insert_tab},
{" help", help, META | '?'} , {"hunt-forward", forwhunt},
{" hunt-backward", backhunt, 0} , {"hunt-backward", backhunt},
{" hunt-forward", forwhunt, META | 'S'} , {"help", help},
{" i-shell", spawncli, CTLX | 'C'} , {"i-shell", spawncli},
{" incremental-search", fisearch, CTLX | 'S'} , #if ISRCH
{"!insert-file", insfile, CTLX | CTL_ | 'I'} , {"incremental-search", fisearch},
{"!insert-space", insspace, CTL_ | 'C'} , #endif
{"!insert-string", istring, 0} , {"insert-file", insfile},
{"insert-space", insspace},
{"insert-string", istring},
#if WORDPRO
#if PKCODE #if PKCODE
{"!justify-paragraph", justpara, META | 'J'} , {"justify-paragraph", justpara},
#endif #endif
{"!kill-paragraph", killpara, META | CTL_ | 'W'} , {"kill-paragraph", killpara},
{"!kill-region", killregion, CTL_ | 'W'} ,
{"!kill-to-end-of-line", killtext, CTL_ | 'K'} ,
{" list-buffers", listbuffers, CTLX | CTL_ | 'B'} ,
{" meta-prefix", (fnp_t) metafn, CTL_ | '['} ,
{" move-window-down", mvdnwind, CTLX | CTL_ | 'N'} ,
{" move-window-up", mvupwind, CTLX | CTL_ | 'P'} ,
{" name-buffer", namebuffer, META | CTL_ | 'N'} ,
{"!newline", insert_newline, CTL_ | 'M'} ,
{"!newline-and-indent", indent, CTL_ | 'J'} ,
{" next-buffer", nextbuffer, CTLX | 'X'} ,
{" next-line", (fnp_t) forwline, CTL_ | 'N'} ,
{" next-page", (fnp_t) forwpage, CTL_ | 'V'} ,
{" next-paragraph", gotoeop, META | 'N'} ,
{" next-window", nextwind, CTLX | 'O'} ,
{" next-word", forwword, META | 'F'} ,
{" nop", (fnp_t) nullproc, META | SPEC | 'C'}, /* hook */
{"!open-line", openline, CTL_ | 'O'} ,
{"!overwrite-string", ovstring, 0} ,
{" pipe-command", pipecmd, CTLX | '@'} ,
{" previous-line", (fnp_t) backline, CTL_ | 'P'} ,
{" previous-page", (fnp_t) backpage, CTL_ | 'Z'} , /* MV */
{" previous-paragraph", gotobop, META | 'P'} ,
{" previous-window", prevwind, CTLX | 'P'} ,
{" previous-word", backword, META | 'B'} ,
{"!query-replace-string", qreplace, META | CTL_ | 'R'} ,
{" quick-exit", quickexit, META | 'Z'} ,
{"!quote-character", quote, CTL_ | 'Q'} ,
{"!read-file", fileread, CTLX | CTL_ | 'R'} ,
{" redraw-display", (fnp_t) reposition, META | CTL_ | 'L'} ,
{"!replace-string", sreplace, META | 'R'} ,
{" resize-window", resize, CTLX | 'W'} ,
{" restore-window", restwnd, 0} ,
{" reverse-incremental-search", risearch, CTLX | 'R'} ,
{" run", execproc, 0} , /* alias of execute-procedure */
{"!save-file", filesave, CTLX | CTL_ | 'S'} , /* also X^D */
{" save-window", savewnd, 0} ,
{" scroll-next-down", scrnextdw, META | CTL_ | 'V'} ,
{" scroll-next-up", scrnextup, META | CTL_ | 'Z'} ,
{" search-forward", forwsearch, CTL_ | 'S'} ,
{" search-reverse", backsearch, CTL_ | 'R'} ,
{" select-buffer", usebuffer, CTLX | 'B'} ,
{" set", setvar, CTLX | 'A'} ,
{" set-fill-column", setfillcol, CTLX | 'F'} ,
{" set-mark", (fnp_t) setmark, META | ' '} , /* M. */
{" shell-command", spawn, CTLX | '!'} ,
{" shrink-window", shrinkwind, CTLX | CTL_ | 'Z'} ,
{" split-current-window", splitwind, CTLX | '2'} ,
{" store-macro", (fnp_t) storemac, 0} ,
{" store-procedure", storeproc, 0} ,
#if BSD | SVR4
{" suspend-emacs", bktoshell, CTLX | 'D'} , /* BSD MS */
#endif #endif
{"!transpose-characters", (fnp_t) twiddle, CTL_ | 'T'} , {"kill-region", killregion},
{"!trim-line", trim, CTLX | CTL_ | 'T'} , {"kill-to-end-of-line", killtext},
{" unbind-key", unbindkey, META | CTL_ | 'K'} , {"list-buffers", listbuffers},
{" universal-argument", (fnp_t) unarg, CTL_ | 'U'} , {"meta-prefix", metafn},
{" unmark-buffer", unmark, META | '~'} , {"move-window-down", mvdnwind},
{" update-screen", (fnp_t) upscreen, 0} , {"move-window-up", mvupwind},
{" view-file", viewfile, CTLX | CTL_ | 'V'} , {"name-buffer", namebuffer},
{"!wrap-word", wrapword, META | SPEC | 'W'} , /* hook */ {"newline", insert_newline},
{" write-file", filewrite, CTLX | CTL_ | 'W'} , {"newline-and-indent", indent},
{" write-message", writemsg, 0} , {"next-buffer", nextbuffer},
{"!yank", yank, CTL_ | 'Y'} , {"next-line", forwline},
{"next-page", forwpage},
{" ", NULL, 0}, #if WORDPRO
/* extra key mapping */ {"next-paragraph", gotoeop},
// { NULL, newsize, META | CTL_ | 'S'},
{ NULL, backdel, CTL_ | '?'},
{ NULL, delbword, META | CTL_ | '?'},
{ NULL, detab, CTLX | CTL_ | 'A'},
{ NULL, enlargewind, CTLX | '^'},
{ NULL, (fnp_t) backpage, META | 'V'},
{ NULL, quote, CTLX | 'Q'},
{ NULL, (fnp_t) reposition, META | '!'},
//detab { NULL, filesave, CTLX | CTL_ | 'D'},
{ NULL, (fnp_t) setmark, META | '.'},
// { NULL, bktoshell, META | 'S'},
/* special key mapping */
{ NULL, yank, SPEC | '2'}, /* Insert */
{ NULL, forwdel /* killregion */, SPEC | '3'}, /* Delete */
{ NULL, (fnp_t) backpage, SPEC | '5'}, /* Page Up */
{ NULL, (fnp_t) forwpage, SPEC | '6'}, /* Page Down */
{ NULL, (fnp_t) backline, SPEC | 'A'}, /* Up */
{ NULL, (fnp_t) forwline, SPEC | 'B'}, /* Down */
{ NULL, (fnp_t) forwchar, SPEC | 'C'}, /* Right */
{ NULL, (fnp_t) backchar, SPEC | 'D'}, /* Left */
{ NULL, (fnp_t) gotoeob, SPEC | 'F'}, /* End */
{ NULL, (fnp_t) gotobob, SPEC | 'H'}, /* Home */
{ NULL, help, SPEC | 'P'}, /* F1 */
/* hooks */
{ NULL, (fnp_t) nullproc, META | SPEC | 'R'}, /* hook */
{ NULL, (fnp_t) nullproc, META | SPEC | 'X'}, /* hook */
{ NULL, NULL, 0}
} ;
static int lastnmidx = 0 ; /* index of last name entry */
kbind_p keytab ;
static int ktsize = 140 ; /* last check: need at least 133 + 1 */
boolean init_bindings( void) {
/* allocate table */
keytab = malloc( ktsize * sizeof *keytab) ;
if( keytab == NULL)
return FALSE ;
/* insert end of table mark */
keytab->k_code = 0 ;
keytab->k_nbp = NULL ;
/* Add default key bindings */
nbind_p nbp ;
for( nbp = names ; nbp->n_func != NULL ; nbp++) {
/* Check entries and strict order */
assert( (nbp->n_name != NULL) &&
((nbp == names) ||
(0 > strcmp( bind_name( nbp - 1), bind_name( nbp)))
)
) ;
/* Add key definition */
if( nbp->n_keycode) {
kbind_p ktp = setkeybinding( nbp->n_keycode, nbp) ;
if( ktp->k_code == 0) /* Table full, no memory left */
return FALSE ;
/* check it was indeed an insertion at end of table not a
* key code re-definition */
assert( (++ktp)->k_code == 0) ;
}
}
/* memorize position after last valid function entry */
lastnmidx = nbp - names ;
/* Process extra key bindings if any */
for( nbp++ ; nbp->n_func != NULL ; nbp++) {
/* Check entry: a keycode and no name */
assert( nbp->n_keycode && (nbp->n_name == NULL)) ;
/* Look for corresponding function and add extra key binding */
nbind_p fnbp ;
for( fnbp = names ; fnbp->n_func != NULL ; fnbp++)
if( fnbp->n_func == nbp->n_func) {
kbind_p ktp = setkeybinding( nbp->n_keycode, fnbp) ;
if( ktp->k_code == 0) /* Table full, no memory left */
return FALSE ;
/* check it was indeed an insertion at end of table not a
* key code re-definition */
assert( (++ktp)->k_code == 0) ;
break ;
}
/* Insure there is a name entry for the keycode */
assert( fnbp->n_func != NULL) ;
}
return TRUE ;
}
kbind_p setkeybinding( unsigned key, nbind_p nbp) {
kbind_p ktp ;
/* search the table to see if it exists */
for( ktp = keytab ; ktp->k_code != 0 ; ktp++)
if( ktp->k_code == key) {
/* it exists, just change it then */
ktp->k_nbp = nbp ;
return ktp ;
}
/* otherwise we need to add it to the end */
/* check if the end marker is at the end of the table */
if( ktp == &keytab[ ktsize - 1]) {
/* out of binding room */
int newsize = ktsize + 10 ;
kbind_p newkeytab = realloc( keytab, newsize * sizeof *keytab) ;
if( newkeytab == NULL)
/* out of space */
return ktp ;
keytab = newkeytab ;
ktp = &keytab[ ktsize - 1] ;
ktsize = newsize ;
}
ktp->k_code = key ; /* add keycode */
ktp->k_nbp = nbp ;
++ktp ; /* and make sure the next is null */
ktp->k_code = 0 ;
ktp->k_nbp = NULL ;
return ktp - 1 ;
}
boolean delkeybinding( unsigned key) {
kbind_p ktp ; /* pointer into the key binding table */
/* search the table to see if the key exists */
for( ktp = keytab ; ktp->k_code != 0 ; ktp++) {
if( ktp->k_code == key) {
/* save the pointer and scan to the end of the table */
kbind_p sav_ktp = ktp ;
while( (++ktp)->k_code != 0) ;
ktp -= 1 ; /* backup to the last legit entry */
/* copy the last entry to the current one */
sav_ktp->k_code = ktp->k_code ;
sav_ktp->k_nbp = ktp->k_nbp ;
/* null out the last one */
ktp->k_code = 0 ;
ktp->k_nbp = NULL ;
return TRUE ;
}
}
return FALSE ;
}
/* This function looks a key binding up in the binding table
*
* int c; key to find what is bound to it
*/
kbind_p getkeybinding( unsigned c) {
kbind_p ktp ;
for( ktp = keytab ; ktp->k_code != 0 ; ktp++)
if (ktp->k_code == c)
break ;
return ktp ;
}
#define BINARY 1
nbind_p fncmatch( char *name) {
#ifdef BINARY
int found = lastnmidx ;
int low = 0 ;
int high = found - 1 ;
do {
int cur = (high + low) / 2 ;
int s = strcmp( name, bind_name( &names[ cur])) ;
if( s < 0)
high = cur - 1 ;
else if( s == 0) {
found = cur ;
break ;
} else
low = cur + 1 ;
} while( low <= high) ;
return &names[ found] ;
#else
nbind_p nbp ;
for( nbp = names ; nbp->n_func != NULL ; nbp++)
if( !strcmp( name, bind_name( nbp)))
break ;
return nbp ;
#endif #endif
} {"next-window", nextwind},
{"next-word", forwword},
{"nop", nullproc},
{"open-line", openline},
{"overwrite-string", ovstring},
{"pipe-command", pipecmd},
{"previous-line", backline},
{"previous-page", backpage},
#if WORDPRO
{"previous-paragraph", gotobop},
#endif
{"previous-window", prevwind},
{"previous-word", backword},
{"query-replace-string", qreplace},
{"quick-exit", quickexit},
{"quote-character", quote},
{"read-file", fileread},
{"redraw-display", reposition},
{"resize-window", resize},
{"restore-window", restwnd},
{"replace-string", sreplace},
#if ISRCH
{"reverse-incremental-search", risearch},
#endif
#if PROC
{"run", execproc},
#endif
{"save-file", filesave},
{"save-window", savewnd},
{"scroll-next-up", scrnextup},
{"scroll-next-down", scrnextdw},
{"search-forward", forwsearch},
{"search-reverse", backsearch},
{"select-buffer", usebuffer},
{"set", setvar},
#if CRYPT
{"set-encryption-key", set_encryption_key},
#endif
{"set-fill-column", setfillcol},
{"set-mark", setmark},
{"shell-command", spawn},
{"shrink-window", shrinkwind},
{"split-current-window", splitwind},
{"store-macro", storemac},
#if PROC
{"store-procedure", storeproc},
#endif
#if BSD | __hpux | SVR4
{"suspend-emacs", bktoshell},
#endif
{"transpose-characters", twiddle},
#if AEDIT
{"trim-line", trim},
#endif
{"unbind-key", unbindkey},
{"universal-argument", unarg},
{"unmark-buffer", unmark},
{"update-screen", upscreen},
{"view-file", viewfile},
{"wrap-word", wrapword},
{"write-file", filewrite},
{"write-message", writemsg},
{"yank", yank},
{"", NULL}
/* user function that does NOTHING (bound to hooks) */ };
TBINDABLE( nullproc) {
return TRUE ;
}
/* dummy function for binding to meta prefix */
TBINDABLE( metafn) {
return TRUE ;
}
/* dummy function for binding to control-x prefix */
TBINDABLE( cex) {
return TRUE ;
}
/* dummy function for binding to universal-argument */
TBINDABLE( unarg) {
return TRUE ;
}
/* end of names.c */

64
names.h
View File

@ -1,62 +1,8 @@
/* names.h -- mapping of functions to names and keys */
#ifndef _NAMES_H_
#define _NAMES_H_
#include "retcode.h"
#define CTL_ 0x01000000 /* Control flag, or'ed in */
#define META 0x02000000 /* Meta flag, or'ed in */
#define CTLX 0x04000000 /* ^X flag, or'ed in */
#define SPEC 0x08000000 /* special key (function keys) */
#define PRFXMASK 0x0F000000 /* prefix mask */
/* Bindable uEMACS function pointer type and definition template */
#define BINDABLE( fname) int fname( boolean f, int n)
#define BBINDABLE( fname) boolean fname( boolean f, int n)
#define TBINDABLE BBINDABLE
typedef BINDABLE( (*fnp_t)) ;
/* Structure for the name binding table. */ /* Structure for the name binding table. */
typedef struct { struct name_bind {
const char *n_name ; /* name starting with one tag character */ char *n_name; /* name of function key */
fnp_t n_func ; /* function the name is bound to */ int (*n_func)(int, int); /* function name is bound to */
unsigned n_keycode ; /* default key assignment, 0 when none */ };
} name_bind ;
typedef const name_bind *nbind_p ; extern struct name_bind names[];/* name to function table */
#define bind_name( p) (&( p)->n_name[ 1])
#define bind_tag( p) ( p)->n_name[ 0]
/* Structure for the key bindings table. */
typedef struct {
unsigned k_code ; /* Key code */
nbind_p k_nbp ; /* entry in name to function map table */
} *kbind_p ;
extern const name_bind names[] ; /* name to function mapping table */
extern kbind_p keytab ; /* key bind to functions table */
boolean init_bindings( void) ;
kbind_p setkeybinding( unsigned key, nbind_p nbp) ;
boolean delkeybinding( unsigned key) ;
kbind_p getkeybinding( unsigned key) ; /* look up by key code */
/* find a name to function association in the name to function mapping table */
nbind_p fncmatch( char *name) ; /* look up by name */
/* bindable functions mapped to prefix keys and hooks */
TBINDABLE( nullproc) ;
TBINDABLE( metafn) ;
TBINDABLE( cex) ;
TBINDABLE( unarg) ;
#endif
/* end of names.h */

View File

@ -1,4 +1,5 @@
/* pklock.c -- implements pklock.h */ /* pklock.c -- implements pklock.h */
#include "estruct.h"
#include "pklock.h" #include "pklock.h"
/* PKLOCK.C /* PKLOCK.C
@ -12,13 +13,14 @@
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
#ifdef SVR4
#include <string.h> #include <string.h>
#else
#include <strings.h>
#endif
#include <errno.h> #include <errno.h>
#include "util.h" #define MAXLOCK 512
/* Maximum file length name 255 */
#define MAXLOCK 256
#define MAXNAME 128 #define MAXNAME 128
#if defined(SVR4) && ! defined(__linux__) #if defined(SVR4) && ! defined(__linux__)
@ -30,7 +32,6 @@ int gethostname(char *name, int namelen)
} }
#endif #endif
char *cuserid( char *retbuf) ; /* should have been declared in stdio.h */
/********************** /**********************
@ -43,13 +44,11 @@ char *cuserid( char *retbuf) ; /* should have been declared in stdio.h */
char *dolock( const char *fname) char *dolock( const char *fname)
{ {
int fd, n; int fd, n;
char lname[ MAXLOCK] ; static char lname[MAXLOCK], locker[MAXNAME + 1];
static char locker[ MAXNAME + 1] ;
int mask; int mask;
struct stat sbuf; struct stat sbuf;
mystrscpy( lname, fname, sizeof lname - 6) ; strcat(strcpy(lname, fname), ".lock~");
strcat( lname, ".lock~") ;
/* check that we are not being cheated, qname must point to */ /* check that we are not being cheated, qname must point to */
/* a regular file - even this code leaves a small window of */ /* a regular file - even this code leaves a small window of */
@ -81,19 +80,8 @@ char *dolock( const char *fname)
} }
if ((n = read(fd, locker, MAXNAME)) < 1) { if ((n = read(fd, locker, MAXNAME)) < 1) {
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
/* /* strcpy(locker, getlogin()); */
** Since Ubuntu 17.04, cuserid prototype seems missing. Replacing it by cuserid(locker);
** getlogin does the trick on 64 bits but fails on 32 bits.
** So let's work around with cuserid for a while.
** logname = getlogin() ;
** strcpy( locker, logname ? logname : cuserid( NULL)) ;
*/
#if BSD
strcpy( locker, getlogin()) ;
#else
strcpy( locker, cuserid( NULL)) ;
#endif
strcat(locker + strlen(locker), "@"); strcat(locker + strlen(locker), "@");
gethostname(locker + strlen(locker), 64); gethostname(locker + strlen(locker), 64);
{ {
@ -123,11 +111,11 @@ char *dolock( const char *fname)
* *
*********************/ *********************/
char *undolock( const char *fname) { char *undolock( const char *fname)
char lname[ MAXLOCK] ; {
static char lname[MAXLOCK];
mystrscpy( lname, fname, sizeof lname - 6) ; strcat(strcpy(lname, fname), ".lock~");
strcat( lname, ".lock~") ;
if (unlink(lname) != 0) { if (unlink(lname) != 0) {
if (errno == EACCES || errno == ENOENT) if (errno == EACCES || errno == ENOENT)
return NULL; return NULL;
@ -139,9 +127,4 @@ char *undolock( const char *fname) {
} }
return NULL; return NULL;
} }
#else
typedef void _pedantic_empty_translation_unit ;
#endif #endif
/* end of pklock.c */

View File

@ -1,13 +1,15 @@
/* pklock.h -- */
#ifndef _PKLOCK_H_ #ifndef _PKLOCK_H_
#define _PKLOCK_H_ #define _PKLOCK_H_
#include "defines.h" /* FILOCK, BSD, SVR4 */ #ifndef _ESTRUCT_H_
#error uEmacs compilation settings needs to be done!
#endif
#if (FILOCK && BSD) || SVR4 #if (FILOCK && BSD) || SVR4
char *dolock( const char *fname) ; char *dolock( const char *fname) ;
char *undolock( const char *fname) ; char *undolock( const char *fname) ;
#endif #endif
#endif #endif
/* end of pklock.h */

106
posix.c
View File

@ -1,17 +1,18 @@
/* posix.c -- posix implementation of termio.h */ /* posix.c -- posix implementation of termio.h */
#include "termio.h"
#include "defines.h" /* POSIX */
#ifdef POSIX #ifdef POSIX
/* The functions in this file negotiate with the operating system for #include "termio.h"
characters, and write characters in a barely buffered fashion on the
display. All operating systems.
modified by Petri Kutvonen /* posix.c
*
based on termio.c, with all the old cruft removed, and * The functions in this file negotiate with the operating system for
fixed for termios rather than the old termio.. Linus Torvalds * 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> #include <errno.h>
@ -23,23 +24,21 @@
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
#include "estruct.h"
#include "retcode.h" #include "retcode.h"
#include "utf8.h" #include "utf8.h"
int ttrow = -1 ; /* Row location of HW cursor */ int ttrow = HUGE ; /* Row location of HW cursor */
int ttcol = -1 ; /* Column location of HW cursor */ int ttcol = HUGE ; /* Column location of HW cursor */
/* Define missing macroes for BSD and CYGWIN environment */ /* Since Mac OS X's termios.h doesn't have the following 2 macros, define them.
#if BSD */
# ifndef OLCUC #if defined(SYSV) && (defined(_DARWIN_C_SOURCE) || defined(_FREEBSD_C_SOURCE))
# define OLCUC 0000002 #define OLCUC 0000002
# endif #define XCASE 0000004
# ifndef XCASE
# define XCASE 0000004
# endif
#endif #endif
#ifdef __CYGWIN__ /* gcc predefined (see cpp -dM) */ #ifdef CYGWIN
#define XCASE 0 #define XCASE 0
#define ECHOPRT 0 #define ECHOPRT 0
#define PENDIN 0 #define PENDIN 0
@ -57,7 +56,8 @@ static char tobuf[TBUFSIZ]; /* terminal output buffer */
/* /*
* This function is called once to set up the terminal device streams. * This function is called once to set up the terminal device streams.
* On CPM it is a no-op. * On VMS, it translates TT until it finds the terminal, then assigns
* a channel to it and sets it raw. On CPM it is a no-op.
*/ */
void ttopen(void) void ttopen(void)
{ {
@ -97,13 +97,15 @@ void ttopen(void)
kbdflgs = fcntl(0, F_GETFL, 0); kbdflgs = fcntl(0, F_GETFL, 0);
kbdpoll = FALSE; kbdpoll = FALSE;
/* on all screens we are not sure of the initial position of the cursor */ /* on all screens we are not sure of the initial position
ttrow = ttcol = -1 ; of the cursor */
ttrow = 999;
ttcol = 999;
} }
/* /*
* This function gets called just before we go back home to the command * This function gets called just before we go back home to the command
* interpreter. * interpreter. On VMS it puts the terminal back in a reasonable state.
* Another no-operation on CPM. * Another no-operation on CPM.
*/ */
void ttclose(void) void ttclose(void)
@ -112,11 +114,13 @@ void ttclose(void)
} }
/* /*
* Write a character to the display. * Write a character to the display. On VMS, terminal output is buffered, and
* we just put the characters in the big array, after checking for overflow.
* On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
* MS-DOS (use the very very raw console output routine). * MS-DOS (use the very very raw console output routine).
*/ */
int ttputc( unicode_t c) { int ttputc(int c)
{
char utf8[6]; char utf8[6];
int bytes; int bytes;
@ -153,28 +157,27 @@ void ttflush(void)
exit(15); exit(15);
} }
/*
/* Read a character from the terminal, performing no editing and doing no * Read a character from the terminal, performing no editing and doing no echo
echo at all. * at all. More complex in VMS that almost anyplace else, which figures. Very
* simple on CPM, because the system can do exactly what you want.
*/ */
int ttgetc( void) { int ttgetc(void)
static char buffer[ 32] ; {
static int pending ; static char buffer[32];
unicode_t c ; static int pending;
unicode_t c;
int count, bytes = 1, expected;
int count = pending ; count = pending;
if( !count) { if (!count) {
count = read( 0, buffer, sizeof( buffer)) ; count = read(0, buffer, sizeof(buffer));
if( count <= 0) if (count <= 0)
return 0 ; return 0;
pending = count;
pending = count ;
} }
int bytes = 1 ; c = (unsigned char) buffer[0];
c = (unsigned char) buffer[ 0] ;
#if 0 // temporary fix for wsl
if (c >= 32 && c < 128) if (c >= 32 && c < 128)
goto done; goto done;
@ -191,7 +194,7 @@ int ttgetc( void) {
* delay for some *very* unusual utf8 character * delay for some *very* unusual utf8 character
* input. * input.
*/ */
int expected = 2; expected = 2;
if ((c & 0xe0) == 0xe0) if ((c & 0xe0) == 0xe0)
expected = 6; expected = 6;
@ -225,10 +228,9 @@ int ttgetc( void) {
bytes = utf8_to_unicode(buffer, 0, pending, &c); bytes = utf8_to_unicode(buffer, 0, pending, &c);
done: done:
#endif pending -= bytes;
pending -= bytes ; memmove(buffer, buffer+bytes, pending);
memmove( buffer, buffer + bytes, pending) ; return c;
return c ;
} }
/* typahead: Check to see if any characters are already in the /* typahead: Check to see if any characters are already in the
@ -248,6 +250,4 @@ int typahead(void)
return x; return x;
} }
#endif #endif /* POSIX */
/* end of posix.c */

1648
random.c

File diff suppressed because it is too large Load Diff

View File

@ -1,46 +1,48 @@
/* random.h -- various commands */
#ifndef _RANDOM_H_ #ifndef _RANDOM_H_
#define _RANDOM_H_ #define _RANDOM_H_
#include "names.h" #define AEDIT 1
/* Command flags */ extern int fillcol ; /* Fill column */
#define CFCPCN 0x0001 /* Flag that last command was C-P, C-N */
#define CFKILL 0x0002 /* Flag that last command was a kill */
extern int thisflag ; /* Flags, this command */
extern int lastflag ; /* Flags, last command */
extern int fillcol ; /* Fill column */
extern boolean hardtab ; /* Use hard tab instead of soft tab */
/* Uninitialized global external declarations. */
#define CFCPCN 0x0001 /* Last command was C-P, C-N */
#define CFKILL 0x0002 /* Last command was a kill */
extern int thisflag ; /* Flags, this command */
extern int lastflag ; /* Flags, last command */
int setfillcol( int f, int n) ;
int showcpos( int f, int n) ;
int getcline( void) ; int getcline( void) ;
int getccol( int bflg) ; int getccol( int bflg) ;
boolean setccol( int pos) ; int setccol( int pos) ;
int twiddle( int f, int n) ;
/* Bindable functions */ int quote( int f, int n) ;
BINDABLE( setfillcol) ; int insert_tab( int f, int n) ;
BINDABLE( showcpos) ; #if AEDIT
BBINDABLE( twiddle) ; int detab( int f, int n) ;
BINDABLE( quote) ; int entab( int f, int n) ;
BINDABLE( insert_tab) ; int trim( int f, int n) ;
BINDABLE( detab) ; #endif
BINDABLE( entab) ; int openline( int f, int n) ;
BINDABLE( trim) ; int insert_newline( int f, int n) ;
BINDABLE( openline) ; int insbrace( int n, int c) ;
BINDABLE( insert_newline) ; int inspound( void) ;
BINDABLE( deblank) ; int deblank( int f, int n) ;
BINDABLE( indent) ; int indent( int f, int n) ;
BINDABLE( forwdel) ; int forwdel( int f, int n) ;
BINDABLE( backdel) ; int backdel( int f, int n) ;
BINDABLE( killtext) ; int killtext( int f, int n) ;
BINDABLE( setemode) ; int setemode( int f, int n) ;
BINDABLE( delmode) ; int delmode( int f, int n) ;
BINDABLE( setgmode) ; int setgmode( int f, int n) ;
BINDABLE( delgmode) ; int delgmode( int f, int n) ;
BINDABLE( istring) ; int getfence( int f, int n) ;
BINDABLE( ovstring) ; int fmatch( int ch) ;
int istring( int f, int n) ;
int ovstring( int f, int n) ;
#endif #endif
/* end of random.h */

258
region.c
View File

@ -1,147 +1,179 @@
/* region.c -- implements region.h */ /* region.c -- implements region.h */
#include "region.h" #include "region.h"
/* The routines in this file deal with the region, that magic space between /* region.c
"." and mark. Some functions are commands. Some functions are just for *
internal use. * The routines in this file deal with the region, that magic space
* between "." and mark. Some functions are commands. Some functions are
Modified by Petri Kutvonen * just for internal use.
*
* Modified by Petri Kutvonen
*/ */
#include <assert.h> #include <stdio.h>
#include <stddef.h>
#include "buffer.h" #include "buffer.h"
#include "defines.h" #include "estruct.h"
#include "line.h" #include "line.h"
#include "mlout.h" #include "mlout.h"
#include "random.h" #include "random.h"
#include "window.h" #include "window.h"
/* Kill the region. Ask getregion() to figure out the bounds of the /*
region. Move "." to the start, and kill the characters. Bound to C-W * Kill the region. Ask "getregion"
kill-region. * to figure out the bounds of the region.
* Move "." to the start, and kill the characters.
* Bound to "C-W".
*/ */
BINDABLE( killregion) { int killregion(int f, int n)
region_t region ; {
int s;
struct region region;
assert( !(curbp->b_mode & MDVIEW)) ; if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return rdonly(); /* we are in read only mode */
int ret = getregion( &region) ; if ((s = getregion(&region)) != TRUE)
if( ret != TRUE) return s;
return ret ; if ((lastflag & CFKILL) == 0) /* This is a kill type */
kdelete(); /* command, so do magic */
if( (lastflag & CFKILL) == 0) /* This is a kill type */ thisflag |= CFKILL; /* kill buffer stuff. */
kdelete() ; /* command, so do magic */ curwp->w_dotp = region.r_linep;
curwp->w_doto = region.r_offset;
thisflag |= CFKILL ; /* kill buffer stuff. */ return ldelete(region.r_size, TRUE);
curwp->w_dotp = region.r_linep ;
curwp->w_doto = region.r_offset ;
return ldelete( region.r_size, TRUE) ;
} }
/* Copy all of the characters in the region to the kill buffer. Don't move /*
dot at all. This is a bit like a kill region followed by a yank. Bound * Copy all of the characters in the
to M-W copy-region. * region to the kill buffer. Don't move dot
* at all. This is a bit like a kill region followed
* by a yank. Bound to "M-W".
*/ */
BINDABLE( copyregion) { int copyregion(int f, int n)
region_t region ; {
struct line *linep;
int loffs;
int s;
struct region region;
int ret = getregion( &region) ; if ((s = getregion(&region)) != TRUE)
if( ret != TRUE) return s;
return ret ; if ((lastflag & CFKILL) == 0) /* Kill type command. */
kdelete();
if( (lastflag & CFKILL) == 0) /* Kill type command. */ thisflag |= CFKILL;
kdelete() ; linep = region.r_linep; /* Current line. */
loffs = region.r_offset; /* Current offset. */
thisflag |= CFKILL ; while (region.r_size--) {
line_p linep = region.r_linep ; /* Current line. */ if (loffs == llength(linep)) { /* End of line. */
int loffs = region.r_offset ; /* Current offset. */ if ((s = kinsert('\n')) != TRUE)
while( region.r_size--) { return s;
if( loffs == llength( linep)) { /* End of line. */ linep = lforw(linep);
ret = kinsert( '\n') ; loffs = 0;
if( ret != TRUE)
return ret ;
linep = lforw( linep) ;
loffs = 0 ;
} else { /* Middle of line. */ } else { /* Middle of line. */
ret = kinsert( lgetc( linep, loffs)) ; if ((s = kinsert(lgetc(linep, loffs))) != TRUE)
if( ret != TRUE) return s;
return ret ; ++loffs;
++loffs ;
} }
} }
mloutstr( "(region copied)") ; mloutstr( "(region copied)") ;
return TRUE ; return TRUE;
} }
/* Lower case region & Upper case region. Zap all of the upper/lower case /*
characters in the region to lower/upper case. Use the region code to * Lower case region. Zap all of the upper
set the limits. Scan the buffer, doing the changes. Call "lchange" to * case characters in the region to lower case. Use
ensure that redisplay is done in all buffers. Bound to C-X C-L * the region code to set the limits. Scan the buffer,
case-region-lower and C-X C-U case-region-upper. * doing the changes. Call "lchange" to ensure that
* redisplay is done in all buffers. Bound to
* "C-X C-L".
*/ */
static int utol( int c) { int lowerregion(int f, int n)
return (c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : -1 ; {
} struct line *linep;
int loffs;
int c;
int s;
struct region region;
static int ltou( int c) { if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return (c >= 'a' && c <= 'z') ? c + 'A' - 'a' : -1 ; return rdonly(); /* we are in read only mode */
} if ((s = getregion(&region)) != TRUE)
return s;
static int caseregion( int (* cconv)( int)) { lchange(WFHARD);
region_t region ; linep = region.r_linep;
loffs = region.r_offset;
assert( !(curbp->b_mode & MDVIEW)) ; while (region.r_size--) {
if (loffs == llength(linep)) {
int ret = getregion( &region) ; linep = lforw(linep);
if( ret != TRUE) loffs = 0;
return ret ;
lchange( WFHARD) ;
line_p linep = region.r_linep ;
int loffs = region.r_offset ;
while( region.r_size--) {
if( loffs == llength( linep)) {
linep = lforw( linep) ;
loffs = 0 ;
} else { } else {
int c = cconv( lgetc( linep, loffs)) ; c = lgetc(linep, loffs);
if( c != -1) if (c >= 'A' && c <= 'Z')
lputc( linep, loffs, c) ; lputc(linep, loffs, c + 'a' - 'A');
++loffs;
++loffs ;
} }
} }
return TRUE;
return TRUE ;
} }
BINDABLE( lowerregion) { /*
return caseregion( utol) ; * Upper case region. Zap all of the lower
} * case characters in the region to upper case. Use
* the region code to set the limits. Scan the buffer,
BINDABLE( upperregion) { * doing the changes. Call "lchange" to ensure that
return caseregion( ltou) ; * redisplay is done in all buffers. Bound to
} * "C-X C-L".
/* This routine figures out the bounds of the region in the current window,
* and fills in the fields of the "region_t" structure pointed to by "rp".
* Because the dot and mark are usually very close together, we scan
* outward from dot looking for mark. This should save time. Return a
* standard code. Callers of this routine should be prepared to get an
* "ABORT" status; we might make this have the conform thing later.
*/ */
int getregion( region_p rp) { int upperregion(int f, int n)
line_p flp, blp ; {
long fsize, bsize ; struct line *linep;
int loffs;
int c;
int s;
struct region region;
if (curwp->w_markp == NULL) if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return mloutfail( "No mark set in this window") ; return rdonly(); /* we are in read only mode */
if ((s = getregion(&region)) != TRUE)
return s;
lchange(WFHARD);
linep = region.r_linep;
loffs = region.r_offset;
while (region.r_size--) {
if (loffs == llength(linep)) {
linep = lforw(linep);
loffs = 0;
} else {
c = lgetc(linep, loffs);
if (c >= 'a' && c <= 'z')
lputc(linep, loffs, c - 'a' + 'A');
++loffs;
}
}
return TRUE;
}
/*
* This routine figures out the
* bounds of the region in the current window, and
* fills in the fields of the "struct region" structure pointed
* to by "rp". Because the dot and mark are usually very
* close together, we scan outward from dot looking for
* mark. This should save time. Return a standard code.
* Callers of this routine should be prepared to get
* an "ABORT" status; we might make this have the
* conform thing later.
*/
int getregion(struct region *rp)
{
struct line *flp;
struct line *blp;
long fsize;
long bsize;
if (curwp->w_markp == NULL) {
mloutstr( "No mark set in this window") ;
return FALSE;
}
if (curwp->w_dotp == curwp->w_markp) { if (curwp->w_dotp == curwp->w_markp) {
rp->r_linep = curwp->w_dotp; rp->r_linep = curwp->w_dotp;
if (curwp->w_doto < curwp->w_marko) { if (curwp->w_doto < curwp->w_marko) {
@ -181,8 +213,6 @@ int getregion( region_p rp) {
} }
} }
} }
mloutstr( "Bug: lost mark") ;
return mloutfail( "Bug: lost mark") ; return FALSE;
} }
/* end of region.c */

View File

@ -1,27 +1,22 @@
/* region.h -- a region starts at the mark and end at the dot */
#ifndef _REGION_H_ #ifndef _REGION_H_
#define _REGION_H_ #define _REGION_H_
#include "line.h" #include "line.h"
/* The starting position of a region, and the size of the region in /*
characters, is kept in a region structure. Used by the region commands. * The starting position of a region, and the size of the region in
* characters, is kept in a region structure. Used by the region commands.
*/ */
typedef struct { struct region {
line_p r_linep ; /* Origin struct line address. */ struct line *r_linep; /* Origin struct line address. */
int r_offset ; /* Origin struct line offset. */ int r_offset; /* Origin struct line offset. */
long r_size ; /* Length in characters. */ long r_size; /* Length in characters. */
} region_t ; };
typedef region_t *region_p ; int killregion( int f, int n) ;
int copyregion( int f, int n) ;
/* Bindable functions */ int lowerregion( int f, int n) ;
BINDABLE( killregion) ; int upperregion( int f, int n) ;
BINDABLE( copyregion) ; int getregion( struct region *rp) ;
BINDABLE( lowerregion) ;
BINDABLE( upperregion) ;
int getregion( region_p rp) ;
#endif #endif
/* end of region.h */

View File

@ -1,23 +1,25 @@
/* retcode.h -- */
#ifndef __RETCODE_H__ #ifndef __RETCODE_H__
#define __RETCODE_H__ #define __RETCODE_H__
#ifdef FALSE #ifdef FALSE
# error "FALSE shouldn't be defined" #undef FALSE
# undef FALSE #endif
#ifdef TRUE
#undef TRUE
#endif #endif
#ifdef TRUE #if 0
# error "TRUE shouldn't be defined" #define FALSE 0 /* False, no, bad, etc. */
# undef TRUE #define TRUE 1 /* True, yes, good, etc. */
#define ABORT 2 /* Death, ^G, abort, etc. */
#define FAILED 3 /* not-quite fatal false return */
#endif #endif
typedef enum { typedef enum {
FALSE, /* 0, false, no, bad, etc. */ FALSE,
TRUE /* 1, true, yes, good, etc. */ TRUE
} boolean ; } boolean ;
#define ABORT 2 /* 2, death, ^G, abort, etc. */ #define ABORT 2
#endif #endif
/* end of retcode.h */

View File

@ -1,10 +0,0 @@
# Visualize Screen Dimensions
select-buffer screensize
insert-string &cat $curwidth &cat "x" $pagelen
insert-string &rig "---------+" &sub 10 $curcol
&sub &div $curwidth 10 1 insert-string "---------+"
insert-string &lef "1234567890" &mod $curwidth 10
&sub $pagelen 3 execute-command-line "insert-string &cat ~n &add $curline 1"
beginning-of-file
unmark-buffer
write-message $line

149
search.c
View File

@ -1,7 +1,9 @@
/* search.c -- implements search.h */ /* search.c -- implements search.h */
#include "search.h" #include "search.h"
/* The functions in this file implement commands that search in the forward /* search.c
*
* The functions in this file implement commands that search in the forward
* and backward directions. There are no special characters in the search * and backward directions. There are no special characters in the search
* strings. Probably should have a regular expression search, or something * strings. Probably should have a regular expression search, or something
* like that. * like that.
@ -58,21 +60,18 @@
* Modified by Petri Kutvonen * Modified by Petri Kutvonen
*/ */
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "basic.h" #include "basic.h"
#include "buffer.h" #include "buffer.h"
#include "defines.h"
#include "display.h" #include "display.h"
#include "estruct.h"
#include "input.h" #include "input.h"
#include "isa.h"
#include "line.h" #include "line.h"
#include "mlout.h" #include "mlout.h"
#include "terminal.h" #include "terminal.h"
#include "util.h"
#include "window.h" #include "window.h"
/* The variable matchlen holds the length of the matched /* The variable matchlen holds the length of the matched
@ -85,7 +84,7 @@
unsigned int matchlen = 0 ; unsigned int matchlen = 0 ;
static unsigned int mlenold = 0 ; static unsigned int mlenold = 0 ;
char *patmatch = NULL ; char *patmatch = NULL ;
static line_p matchline = NULL; static struct line *matchline = NULL;
static int matchoff = 0; static int matchoff = 0;
spat_t pat ; /* Search pattern */ spat_t pat ; /* Search pattern */
@ -124,6 +123,7 @@ spat_t rpat ; /* replacement pattern */
#define MC_ESC '\\' /* Escape - suppress meta-meaning. */ #define MC_ESC '\\' /* Escape - suppress meta-meaning. */
#define BIT(n) (1 << (n)) /* An integer with one bit set. */ #define BIT(n) (1 << (n)) /* An integer with one bit set. */
#define CHCASE(c) ((c) ^ DIFCASE) /* Toggle the case of a letter. */
/* HICHAR - 1 is the largest character we will deal with. /* HICHAR - 1 is the largest character we will deal with.
* HIBYTE represents the number of bytes in the bitmap. * HIBYTE represents the number of bytes in the bitmap.
@ -163,10 +163,10 @@ static struct magic_replacement rmcpat[NPAT]; /* The replacement magic array. */
static int mcscanner( struct magic *mcpatrn, int direct, int beg_or_end) ; static int mcscanner( struct magic *mcpatrn, int direct, int beg_or_end) ;
#endif #endif
static int amatch(struct magic *mcptr, int direct, line_p *pcwline, int *pcwoff); static int amatch(struct magic *mcptr, int direct, struct line **pcwline, int *pcwoff);
static int readpattern(char *prompt, char *apat, int srch); static int readpattern(char *prompt, char *apat, int srch);
static int replaces(int kind, int f, int n); static int replaces(int kind, int f, int n);
static int nextch( line_p *pcurline, int *pcuroff, int dir); static int nextch(struct line **pcurline, int *pcuroff, int dir);
static int mcstr(void); static int mcstr(void);
static int rmcstr(void); static int rmcstr(void);
static int mceq(int bc, struct magic *mt); static int mceq(int bc, struct magic *mt);
@ -175,14 +175,15 @@ static int biteq(int bc, char *cclmap);
static char *clearbits(void); static char *clearbits(void);
static void setbit(int bc, char *cclmap); static void setbit(int bc, char *cclmap);
/*
/* forwsearch -- Search forward. Get a search string from the user, and * forwsearch -- Search forward. Get a search string from the user, and
* search for the string. If found, reset the "." to be just after * search for the string. If found, reset the "." to be just after
* the match string, and (perhaps) repaint the display. * the match string, and (perhaps) repaint the display.
* *
* int f, n; default flag / numeric argument * int f, n; default flag / numeric argument
*/ */
BINDABLE( forwsearch) { int forwsearch(int f, int n)
{
int status = TRUE; int status = TRUE;
/* If n is negative, search backwards. /* If n is negative, search backwards.
@ -220,14 +221,15 @@ BINDABLE( forwsearch) {
return status; return status;
} }
/*
/* forwhunt -- Search forward for a previously acquired search string. * forwhunt -- Search forward for a previously acquired search string.
* If found, reset the "." to be just after the match string, * If found, reset the "." to be just after the match string,
* and (perhaps) repaint the display. * and (perhaps) repaint the display.
* *
* int f, n; default flag / numeric argument * int f, n; default flag / numeric argument
*/ */
BINDABLE( forwhunt) { int forwhunt(int f, int n)
{
int status = TRUE; int status = TRUE;
if (n < 0) /* search backwards */ if (n < 0) /* search backwards */
@ -272,15 +274,16 @@ BINDABLE( forwhunt) {
return status; return status;
} }
/*
/* backsearch -- Reverse search. Get a search string from the user, and * backsearch -- Reverse search. Get a search string from the user, and
* search, starting at "." and proceeding toward the front of the buffer. * search, starting at "." and proceeding toward the front of the buffer.
* If found "." is left pointing at the first character of the pattern * If found "." is left pointing at the first character of the pattern
* (the last character that was matched). * (the last character that was matched).
* *
* int f, n; default flag / numeric argument * int f, n; default flag / numeric argument
*/ */
BINDABLE( backsearch) { int backsearch(int f, int n)
{
int status = TRUE; int status = TRUE;
/* If n is negative, search forwards. /* If n is negative, search forwards.
@ -319,15 +322,16 @@ BINDABLE( backsearch) {
return status; return status;
} }
/*
/* backhunt -- Reverse search for a previously acquired search string, * backhunt -- Reverse search for a previously acquired search string,
* starting at "." and proceeding toward the front of the buffer. * starting at "." and proceeding toward the front of the buffer.
* If found "." is left pointing at the first character of the pattern * If found "." is left pointing at the first character of the pattern
* (the last character that was matched). * (the last character that was matched).
* *
* int f, n; default flag / numeric argument * int f, n; default flag / numeric argument
*/ */
BINDABLE( backhunt) { int backhunt(int f, int n)
{
int status = TRUE; int status = TRUE;
if (n < 0) if (n < 0)
@ -384,7 +388,7 @@ BINDABLE( backhunt) {
*/ */
static int mcscanner(struct magic *mcpatrn, int direct, int beg_or_end) static int mcscanner(struct magic *mcpatrn, int direct, int beg_or_end)
{ {
line_p curline; /* current line during scan */ struct line *curline; /* current line during scan */
int curoff; /* position within current line */ int curoff; /* position within current line */
/* If we are going in reverse, then the 'end' is actually /* If we are going in reverse, then the 'end' is actually
@ -407,7 +411,7 @@ static int mcscanner(struct magic *mcpatrn, int direct, int beg_or_end)
/* Scan each character until we hit the head link record. /* Scan each character until we hit the head link record.
*/ */
while (!boundary(curline, curoff, direct)) { while (!boundry(curline, curoff, direct)) {
/* Save the current position in case we need to /* Save the current position in case we need to
* restore it on a match, and initialize matchlen to * restore it on a match, and initialize matchlen to
* zero in case we are doing a search for replacement. * zero in case we are doing a search for replacement.
@ -448,13 +452,13 @@ static int mcscanner(struct magic *mcpatrn, int direct, int beg_or_end)
* *
* struct magic *mcptr; string to scan for * struct magic *mcptr; string to scan for
* int direct; which way to go. * int direct; which way to go.
* line_p *pcwline; current line during scan * struct line **pcwline; current line during scan
* int *pcwoff; position within current line * int *pcwoff; position within current line
*/ */
static int amatch(struct magic *mcptr, int direct, line_p *pcwline, int *pcwoff) static int amatch(struct magic *mcptr, int direct, struct line **pcwline, int *pcwoff)
{ {
int c; /* character at current position */ int c; /* character at current position */
line_p curline; /* current line during scan */ struct line *curline; /* current line during scan */
int curoff; /* position within current line */ int curoff; /* position within current line */
int nchars; int nchars;
@ -594,9 +598,9 @@ int scanner(const char *patrn, int direct, int beg_or_end)
{ {
int c; /* character at current position */ int c; /* character at current position */
const char *patptr; /* pointer into pattern */ const char *patptr; /* pointer into pattern */
line_p curline; /* current line during scan */ struct line *curline; /* current line during scan */
int curoff; /* position within current line */ int curoff; /* position within current line */
line_p scanline; /* current line during scanning */ struct line *scanline; /* current line during scanning */
int scanoff; /* position in scanned line */ int scanoff; /* position in scanned line */
/* If we are going in reverse, then the 'end' is actually /* If we are going in reverse, then the 'end' is actually
@ -611,7 +615,7 @@ int scanner(const char *patrn, int direct, int beg_or_end)
/* Scan each character until we hit the head link record. /* Scan each character until we hit the head link record.
*/ */
while (!boundary(curline, curoff, direct)) { while (!boundry(curline, curoff, direct)) {
/* Save the current position in case we match /* Save the current position in case we match
* the search string at this point. * the search string at this point.
*/ */
@ -668,18 +672,19 @@ int scanner(const char *patrn, int direct, int beg_or_end)
int eq(unsigned char bc, unsigned char pc) int eq(unsigned char bc, unsigned char pc)
{ {
if ((curwp->w_bufp->b_mode & MDEXACT) == 0) { if ((curwp->w_bufp->b_mode & MDEXACT) == 0) {
if( islower( bc)) if (islower(bc))
bc = flipcase( bc) ; bc ^= DIFCASE;
if( islower( pc)) if (islower(pc))
pc = flipcase( pc) ; pc ^= DIFCASE;
} }
return bc == pc; return bc == pc;
} }
void setprompt( char *tpat, unsigned tpat_size, char *prompt, char *apat) { void setprompt( char *tpat, unsigned tpat_size, char *prompt, char *apat) {
mystrscpy( tpat, prompt, 15) ; /* copy prompt to output string */ strncpy( tpat, prompt, 14) ; /* copy prompt to output string */
tpat[ 14] = '\0' ; /* longest prompt is "Reverse Search" */
strcat( tpat, " (") ; /* build new prompt string */ strcat( tpat, " (") ; /* build new prompt string */
expandp( apat, &tpat[ strlen( tpat)], tpat_size) ; /* add old pattern */ expandp( apat, &tpat[ strlen( tpat)], tpat_size) ; /* add old pattern */
strcat( tpat, ")<Meta>: ") ; strcat( tpat, ")<Meta>: ") ;
@ -711,7 +716,8 @@ static int readpattern(char *prompt, char *apat, int srch)
*/ */
status = newmlargt( &dynpat, tpat, NPAT) ; status = newmlargt( &dynpat, tpat, NPAT) ;
if( status == TRUE) { if( status == TRUE) {
mystrscpy( apat, dynpat, NPAT) ; strncpy( apat, dynpat, NPAT - 1) ;
apat[ NPAT - 1] = 0 ;
free( dynpat) ; free( dynpat) ;
if (srch) { /* If we are doing the search string. */ if (srch) { /* If we are doing the search string. */
/* Reverse string copy, and remember /* Reverse string copy, and remember
@ -743,7 +749,7 @@ static int readpattern(char *prompt, char *apat, int srch)
void savematch(void) void savematch(void)
{ {
char *ptr; /* pointer to last match string */ char *ptr; /* pointer to last match string */
line_p curline; /* line of last match */ struct line *curline; /* line of last match */
int curoff; /* offset " " */ int curoff; /* offset " " */
/* Free any existing match string, then /* Free any existing match string, then
@ -782,24 +788,26 @@ void rvstrcpy(char *rvstr, char *str)
*rvstr = '\0'; *rvstr = '\0';
} }
/*
/* sreplace -- Search and replace. * sreplace -- Search and replace.
* *
* int f; default flag * int f; default flag
* int n; # of repetitions wanted * int n; # of repetitions wanted
*/ */
BINDABLE( sreplace) { int sreplace(int f, int n)
return replaces( FALSE, f, n) ; {
return replaces(FALSE, f, n);
} }
/*
/* qreplace -- search and replace with query. * qreplace -- search and replace with query.
* *
* int f; default flag * int f; default flag
* int n; # of repetitions wanted * int n; # of repetitions wanted
*/ */
BINDABLE( qreplace) { int qreplace(int f, int n)
return replaces( TRUE, f, n) ; {
return replaces(TRUE, f, n);
} }
/* /*
@ -820,16 +828,17 @@ static int replaces(int kind, int f, int n)
int nlrepl; /* was a replace done on the last line? */ int nlrepl; /* was a replace done on the last line? */
char c; /* input char for query */ char c; /* input char for query */
spat_t tpat ; /* temporary to hold search pattern */ spat_t tpat ; /* temporary to hold search pattern */
line_p origline; /* original "." position */ struct line *origline; /* original "." position */
int origoff; /* and offset (for . query option) */ int origoff; /* and offset (for . query option) */
line_p lastline; /* position of last replace and */ struct line *lastline; /* position of last replace and */
int lastoff; /* offset (for 'u' query option) */ int lastoff; /* offset (for 'u' query option) */
///* rfi */ /* rfi */
lastline = NULL ; lastline = NULL ;
lastoff = 0 ; lastoff = 0 ;
assert( !(curbp->b_mode & MDVIEW)) ; if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return rdonly(); /* we are in read only mode */
/* Check for negative repetitions. /* Check for negative repetitions.
*/ */
@ -1106,23 +1115,25 @@ int expandp(char *srcstr, char *deststr, int maxlength)
return TRUE; return TRUE;
} }
/*
/* boundary -- Returns information depending on whether we may search no * boundry -- Return information depending on whether we may search no
further. Beginning of file and end of file are the obvious cases, but * further. Beginning of file and end of file are the obvious
we may want to add further optional boundary restrictions in future, a' * cases, but we may want to add further optional boundry restrictions
la VMS EDT. At the moment, just return TRUE or FALSE depending on if a * in future, a' la VMS EDT. At the moment, just return TRUE or
boundary is hit (ouch). * FALSE depending on if a boundry is hit (ouch).
*/ */
int boundary( line_p curline, int curoff, int dir) { int boundry(struct line *curline, int curoff, int dir)
int border ; {
int border;
if( dir == FORWARD) if (dir == FORWARD) {
border = (curoff == llength( curline)) && border = (curoff == llength(curline)) &&
(lforw( curline) == curbp->b_linep) ; (lforw(curline) == curbp->b_linep);
else } else {
border = (curoff == 0) && (lback( curline) == curbp->b_linep) ; border = (curoff == 0) &&
(lback(curline) == curbp->b_linep);
return border ; }
return border;
} }
/* /*
@ -1133,9 +1144,9 @@ int boundary( line_p curline, int curoff, int dir) {
* the current character and move, reverse searches move and * the current character and move, reverse searches move and
* look at the character. * look at the character.
*/ */
static int nextch( line_p *pcurline, int *pcuroff, int dir) static int nextch(struct line **pcurline, int *pcuroff, int dir)
{ {
line_p curline; struct line *curline;
int curoff; int curoff;
int c; int c;
@ -1277,7 +1288,7 @@ static int mcstr(void)
if (status) { if (status) {
rtpcm = &tapcm[0]; rtpcm = &tapcm[0];
while (--mj >= 0) { while (--mj >= 0) {
#if USG | BSD #if MSC | TURBO | VMS | USG | BSD | V7
*rtpcm++ = *--mcptr; *rtpcm++ = *--mcptr;
#endif #endif
} }
@ -1445,7 +1456,7 @@ static int mceq(int bc, struct magic *mt)
if (!(result = biteq(bc, mt->u.cclmap))) { if (!(result = biteq(bc, mt->u.cclmap))) {
if ((curwp->w_bufp->b_mode & MDEXACT) == 0 && if ((curwp->w_bufp->b_mode & MDEXACT) == 0 &&
(isletter(bc))) { (isletter(bc))) {
result = biteq( flipcase( bc), mt->u.cclmap) ; result = biteq(CHCASE(bc), mt->u.cclmap);
} }
} }
break; break;
@ -1455,7 +1466,7 @@ static int mceq(int bc, struct magic *mt)
if ((curwp->w_bufp->b_mode & MDEXACT) == 0 && if ((curwp->w_bufp->b_mode & MDEXACT) == 0 &&
(isletter(bc))) { (isletter(bc))) {
result &= !biteq( flipcase( bc), mt->u.cclmap) ; result &= !biteq(CHCASE(bc), mt->u.cclmap);
} }
break; break;
@ -1532,7 +1543,7 @@ static int cclmake(char **ppatptr, struct magic *mcptr)
*/ */
case MC_ESC: case MC_ESC:
pchr = *++patptr; pchr = *++patptr;
/* fallthrough */ /* falltrhough */
default: default:
setbit(pchr, bmap); setbit(pchr, bmap);
break; break;
@ -1594,5 +1605,3 @@ static void setbit(int bc, char *cclmap)
*(cclmap + (bc >> 3)) |= BIT(bc & 7); *(cclmap + (bc >> 3)) |= BIT(bc & 7);
} }
#endif #endif
/* end of search.c */

View File

@ -1,53 +1,49 @@
/* search.h -- */
#ifndef _SEARCH_H_ #ifndef _SEARCH_H_
#define _SEARCH_H_ #define _SEARCH_H_
#include "line.h" /* line_p */ #define MAGIC 1 /* include regular expression matching? */
#include "names.h" /* BINDABLE() */
typedef char spat_t[ 128] ; /* search pattern type */ #include "line.h"
#define NPAT sizeof( spat_t) /* # of bytes, pattern */
typedef char spat_t[ 128] ; /* search pattern type */
#define NPAT sizeof( spat_t) /* # of bytes, pattern */
extern unsigned int matchlen ; extern unsigned int matchlen ;
extern char *patmatch ; extern char *patmatch ;
extern spat_t pat ; /* Search pattern */ extern spat_t pat ; /* Search pattern */
extern spat_t tap ; /* Reversed pattern array. */ extern spat_t tap ; /* Reversed pattern array. */
extern spat_t rpat ; /* replacement pattern */ extern spat_t rpat ; /* replacement pattern */
/* /*
* PTBEG, PTEND, FORWARD, and REVERSE are all toggle-able values for * PTBEG, PTEND, FORWARD, and REVERSE are all toggle-able values for
* the scan routines. * the scan routines.
*/ */
#define PTBEG 0 /* Leave the point at the beginning on search */ #define PTBEG 0 /* Leave the point at the beginning on search */
#define PTEND 1 /* Leave the point at the end on search */ #define PTEND 1 /* Leave the point at the end on search */
#define FORWARD 0 /* forward direction */ #define FORWARD 0 /* forward direction */
#define REVERSE 1 /* backwards direction */ #define REVERSE 1 /* backwards direction */
int scanner( const char *patrn, int direct, int beg_or_end) ; int scanner( const char *patrn, int direct, int beg_or_end) ;
/* Bindable functions */ int forwsearch( int f, int n) ;
BINDABLE( backhunt) ; int forwhunt( int f, int n) ;
BINDABLE( backsearch) ; int backsearch( int f, int n) ;
BINDABLE( forwhunt) ; int backhunt( int f, int n) ;
BINDABLE( forwsearch) ;
BINDABLE( qreplace) ;
BINDABLE( sreplace) ;
int eq( unsigned char bc, unsigned char pc) ; int eq( unsigned char bc, unsigned char pc) ;
void savematch( void) ; void savematch( void) ;
void rvstrcpy( char *rvstr, char *str) ; void rvstrcpy( char *rvstr, char *str) ;
int sreplace( int f, int n) ;
int qreplace( int f, int n) ;
int delins( int dlength, char *instr, int use_meta) ; int delins( int dlength, char *instr, int use_meta) ;
int expandp( char *srcstr, char *deststr, int maxlength) ; int expandp( char *srcstr, char *deststr, int maxlength) ;
int boundary( line_p curline, int curoff, int dir) ; int boundry( struct line *curline, int curoff, int dir) ;
void setprompt( char *tpat, unsigned tpat_size, char *prompt, char *apat) ; void setprompt( char *tpat, unsigned tpat_size, char *prompt, char *apat) ;
#define MAGIC 1 /* include regular expression matching? */
#if MAGIC #if MAGIC
void mcclear( void) ; void mcclear( void) ;
void rmcclear( void) ; void rmcclear( void) ;
#endif #endif
#endif #endif
/* end of search.h */

View File

@ -1,54 +0,0 @@
## 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

362
spawn.c
View File

@ -1,20 +1,23 @@
/* spawn.c -- implements spawn.h */ /* spawn.c -- implements spawn.h */
#include "spawn.h" #include "spawn.h"
/* Various operating system access commands. /* spawn.c
* *
* Modified by Petri Kutvonen * Various operating system access commands.
*
* <odified by Petri Kutvonen
*/ */
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "buffer.h"
#include "defines.h" #include "defines.h"
#include "buffer.h"
#include "display.h" #include "display.h"
#include "estruct.h"
#include "exec.h" #include "exec.h"
#include "file.h" #include "file.h"
#include "flook.h" #include "flook.h"
@ -22,18 +25,39 @@
#include "terminal.h" #include "terminal.h"
#include "window.h" #include "window.h"
#if VMS
#define EFN 0 /* Event flag. */
#if USG | BSD #include <ssdef.h> /* Random headers. */
#include <stsdef.h>
#include <descrip.h>
#include <iodef.h>
extern int oldmode[3]; /* In "termio.c" */
extern int newmode[3]; /* In "termio.c" */
extern short iochan; /* In "termio.c" */
#endif
#if V7 | USG | BSD
#include <signal.h> #include <signal.h>
#ifdef SIGWINCH
#endif
#endif
#if MSDOS & (MSC | TURBO)
#include <process.h>
#endif #endif
/* Create a subjob with a copy of the command intrepreter in it. When the /*
* Create a subjob with a copy of the command intrepreter in it. When the
* command interpreter exits, mark the screen as garbage so that you do a full * command interpreter exits, mark the screen as garbage so that you do a full
* repaint. Bound to "^X C". * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
* Under some (unknown) condition, you don't get one free when DCL starts up.
*/ */
BINDABLE( spawncli) { int spawncli(int f, int n)
#if USG | BSD {
#if V7 | USG | BSD
char *cp; char *cp;
#endif #endif
@ -41,7 +65,28 @@ BINDABLE( spawncli) {
if (restflag) if (restflag)
return resterr(); return resterr();
#if USG | BSD #if VMS
movecursor(term.t_nrow, 0); /* In last line. */
mlwrite("(Starting DCL)\r\n");
TTflush(); /* Ignore "ttcol". */
sgarbf = TRUE;
sys(NULL);
sleep(1);
mlwrite("\r\n(Returning from DCL)\r\n");
TTflush();
sleep(1);
return TRUE;
#endif
#if MSDOS & (MSC | TURBO)
movecursor(term.t_nrow, 0); /* Seek to last line. */
TTflush();
TTkclose();
shellprog("");
TTkopen();
sgarbf = TRUE;
return TRUE;
#endif
#if V7 | USG | BSD
movecursor(term.t_nrow, 0); /* Seek to last line. */ movecursor(term.t_nrow, 0); /* Seek to last line. */
TTflush(); TTflush();
TTclose(); /* stty to old settings */ TTclose(); /* stty to old settings */
@ -72,9 +117,10 @@ BINDABLE( spawncli) {
#endif #endif
} }
#if BSD | SVR4 #if BSD | __hpux | SVR4
/* suspend MicroEMACS and wait to wake up */
BINDABLE( bktoshell) { int bktoshell(int f, int n)
{ /* suspend MicroEMACS and wait to wake up */
vttidy(); vttidy();
/****************************** /******************************
int pid; int pid;
@ -94,12 +140,12 @@ void rtfrmshell(void)
} }
#endif #endif
/*
/* Run a one-liner in a subjob. When the command returns, wait for a single * Run a one-liner in a subjob. When the command returns, wait for a single
* character to be typed, then mark the screen as garbage so a full repaint is * character to be typed, then mark the screen as garbage so a full repaint is
* done. Bound to "C-X !". * done. Bound to "C-X !".
*/ */
BINDABLE( spawn) { int spawn( int f, int n) {
int s ; int s ;
char *line ; char *line ;
@ -107,7 +153,7 @@ BINDABLE( spawn) {
if( restflag) if( restflag)
return resterr(); return resterr();
#if USG | BSD #if V7 | USG | BSD
s = newmlarg( &line, "!", 0) ; s = newmlarg( &line, "!", 0) ;
if( s != TRUE) if( s != TRUE)
return s ; return s ;
@ -132,13 +178,13 @@ BINDABLE( spawn) {
#endif #endif
} }
/*
/* Run an external program with arguments. When it returns, wait for a single * Run an external program with arguments. When it returns, wait for a single
* character to be typed, then mark the screen as garbage so a full repaint is * character to be typed, then mark the screen as garbage so a full repaint is
* done. Bound to "C-X $". * done. Bound to "C-X $".
*/ */
BINDABLE( execprg) { int execprg( int f, int n) {
int s ; int s ;
char *line ; char *line ;
@ -146,7 +192,7 @@ BINDABLE( execprg) {
if( restflag) if( restflag)
return resterr() ; return resterr() ;
#if USG | BSD #if V7 | USG | BSD
s = newmlarg( &line, "$", 0) ; s = newmlarg( &line, "$", 0) ;
if( s != TRUE) if( s != TRUE)
return s ; return s ;
@ -167,99 +213,108 @@ BINDABLE( execprg) {
#endif #endif
} }
/*
/* Pipe a one line command into a window * Pipe a one line command into a window
* Bound to pipe-command ^X @ * Bound to ^X @
*/ */
BINDABLE( pipecmd) { int pipecmd( int f, int n) {
window_p wp ; /* pointer to new window */ int s ; /* return status from CLI */
struct window *wp ; /* pointer to new window */
struct buffer *bp ; /* pointer to buffer to zot */
char *mlarg ; char *mlarg ;
const char filnam[] = "command" ; char *line ; /* command line send to shell */
static char bname[] = "command" ;
static char filnam[ NSTRING] = "command" ;
/* don't allow this command if restricted */ /* don't allow this command if restricted */
if( restflag) if( restflag)
return resterr() ; return resterr() ;
/* get the command to pipe in */ /* get the command to pipe in */
int s = newmlarg( &mlarg, "pipe-command: ", 0) ; s = newmlarg( &mlarg, "@", 0) ;
if( s != TRUE) if( s != TRUE)
return s ; return s ;
char *cmdline = malloc( strlen( mlarg) + strlen( filnam) + 4) ; line = malloc( strlen( mlarg) + strlen( filnam) + 2) ;
if( cmdline == NULL) { if( line == NULL) {
free( mlarg) ; free( mlarg) ;
return FALSE ; return FALSE ;
} }
strcpy( cmdline, mlarg) ; strcpy( line, mlarg) ;
free( mlarg) ; free( mlarg) ;
strcat( cmdline, " > ") ;
strcat( cmdline, filnam) ;
/* get rid of the command output buffer if it exists */ /* get rid of the command output buffer if it exists */
buffer_p bp = bfind( filnam, FALSE, 0) ; if ((bp = bfind(bname, FALSE, 0)) != FALSE) {
if( bp != NULL) { /* try to make sure we are off screen */
/* try to make sure we are off screen */ wp = wheadp;
for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) { while (wp != NULL) {
if( wp->w_bufp == bp) { if (wp->w_bufp == bp) {
#if PKCODE #if PKCODE
if( wp == curwp) if (wp == curwp)
delwind( FALSE, 1) ; delwind(FALSE, 1);
else else
onlywind( FALSE, 1) ; onlywind(FALSE, 1);
break ; break;
#else #else
onlywind( FALSE, 1) ; onlywind(FALSE, 1);
break ; break;
#endif #endif
} }
wp = wp->w_wndp;
} }
if( zotbuf( bp) != TRUE) { if( zotbuf( bp) != TRUE) {
free( cmdline) ; free( line) ;
return FALSE ; return FALSE ;
} }
} }
#if V7 | USG | BSD
#if USG | BSD
TTflush(); TTflush();
TTclose(); /* stty to old modes */ TTclose(); /* stty to old modes */
TTkclose(); TTkclose();
ue_system( cmdline) ; strcat( line, ">") ;
free( cmdline) ; strcat( line, filnam) ;
ue_system( line) ;
free( line) ;
TTopen(); TTopen();
TTkopen(); TTkopen();
TTflush(); TTflush();
sgarbf = TRUE; sgarbf = TRUE;
s = TRUE; s = TRUE;
#else #else
if( s != TRUE) if (s != TRUE)
return s; return s;
#endif #endif
/* split the current window to make room for the command output /* split the current window to make room for the command output */
** and read the stuff in */ if (splitwind(FALSE, 1) == FALSE)
if( splitwind( FALSE, 1) == FALSE return FALSE;
|| getfile( filnam, FALSE) == FALSE)
return FALSE ;
/* make this window in VIEW mode, update all mode lines */ /* and read the stuff in */
curwp->w_bufp->b_mode |= MDVIEW ; if (getfile(filnam, FALSE) == FALSE)
for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp) return FALSE;
wp->w_flag |= WFMODE ;
/* and get rid of the temporary file */ /* make this window in VIEW mode, update all mode lines */
unlink( filnam) ; curwp->w_bufp->b_mode |= MDVIEW;
return TRUE ; wp = wheadp;
while (wp != NULL) {
wp->w_flag |= WFMODE;
wp = wp->w_wndp;
}
/* and get rid of the temporary file */
unlink(filnam);
return TRUE;
} }
/*
/* filter a buffer through an external DOS program * filter a buffer through an external DOS program
* Bound to ^X # * Bound to ^X #
*/ */
BINDABLE( filter_buffer) { int filter_buffer( int f, int n) {
int s ; /* return status from CLI */ int s ; /* return status from CLI */
buffer_p bp ; /* pointer to buffer to zot */ struct buffer *bp ; /* pointer to buffer to zot */
char *mlarg ; char *mlarg ;
char *line ; /* command line send to shell */ char *line ; /* command line send to shell */
fname_t tmpnam ; /* place to store real file name */ fname_t tmpnam ; /* place to store real file name */
@ -272,7 +327,8 @@ BINDABLE( filter_buffer) {
if( restflag) if( restflag)
return resterr() ; return resterr() ;
assert( !(curbp->b_mode & MDVIEW)) ; if( curbp->b_mode & MDVIEW) /* don't allow this command if */
return rdonly() ; /* we are in read only mode */
/* get the filter name and its args */ /* get the filter name and its args */
s = newmlarg( &mlarg, "#", 0) ; s = newmlarg( &mlarg, "#", 0) ;
@ -301,7 +357,7 @@ BINDABLE( filter_buffer) {
return FALSE ; return FALSE ;
} }
#if USG | BSD #if V7 | USG | BSD
TTputc('\n'); /* Already have '\r' */ TTputc('\n'); /* Already have '\r' */
TTflush(); TTflush();
TTclose(); /* stty to old modes */ TTclose(); /* stty to old modes */
@ -335,4 +391,166 @@ BINDABLE( filter_buffer) {
return TRUE; return TRUE;
} }
/* end of spawn.c */ #if VMS
/*
* Run a command. The "cmd" is a pointer to a command string, or NULL if you
* want to run a copy of DCL in the subjob (this is how the standard routine
* LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in
* and the way out, because DCL does not want the channel to be in raw mode.
*/
int sys(char *cmd)
{
struct dsc$descriptor cdsc;
struct dsc$descriptor *cdscp;
long status;
long substatus;
long iosb[2];
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
oldmode, sizeof(oldmode), 0, 0, 0, 0);
if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL)
return FALSE;
cdscp = NULL; /* Assume DCL. */
if (cmd != NULL) { /* Build descriptor. */
cdsc.dsc$a_pointer = cmd;
cdsc.dsc$w_length = strlen(cmd);
cdsc.dsc$b_dtype = DSC$K_DTYPE_T;
cdsc.dsc$b_class = DSC$K_CLASS_S;
cdscp = &cdsc;
}
status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
if (status != SS$_NORMAL)
substatus = status;
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
newmode, sizeof(newmode), 0, 0, 0, 0);
if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL)
return FALSE;
if ((substatus & STS$M_SUCCESS) == 0) /* Command failed. */
return FALSE;
return TRUE;
}
#endif
#if MSDOS & (TURBO | MSC)
/*
* SHELLPROG: Execute a command in a subshell
*
* char *cmd; Incoming command line to execute
*/
int shellprog(char *cmd)
{
char *shell; /* Name of system command processor */
char *p; /* Temporary pointer */
char swchar; /* switch character to use */
union REGS regs; /* parameters for dos call */
char comline[NSTRING]; /* constructed command line */
/* detect current switch character and set us up to use it */
regs.h.ah = 0x37; /* get setting data */
regs.h.al = 0x00; /* get switch character */
intdos(&regs, &regs);
swchar = (char) regs.h.dl;
/* get name of system shell */
if ((shell = getenv("COMSPEC")) == NULL) {
return FALSE; /* No shell located */
}
/* trim leading whitespace off the command */
while (*cmd == ' ' || *cmd == '\t') /* find out if null command */
cmd++;
/** If the command line is not empty, bring up the shell **/
/** and execute the command. Otherwise, bring up the **/
/** shell in interactive mode. **/
if (*cmd) {
strcpy(comline, shell);
strcat(comline, " ");
comline[strlen(comline) + 1] = 0;
comline[strlen(comline)] = swchar;
strcat(comline, "c ");
strcat(comline, cmd);
return execprog(comline);
} else
return execprog(shell);
}
/*
* EXECPROG:
* A function to execute a named program
* with arguments
*
* char *cmd; Incoming command line to execute
*/
int execprog(char *cmd)
{
char *sp; /* temporary string pointer */
char f1[38]; /* FCB1 area (not initialized */
char f2[38]; /* FCB2 area (not initialized */
char prog[NSTRING]; /* program filespec */
char tail[NSTRING]; /* command tail with length byte */
union REGS regs; /* parameters for dos call */
struct SREGS segreg; /* segment registers for dis call */
struct pblock { /* EXEC parameter block */
short envptr; /* 2 byte pointer to environment string */
char *cline; /* 4 byte pointer to command line */
char *fcb1; /* 4 byte pointer to FCB at PSP+5Ch */
char *fcb2; /* 4 byte pointer to FCB at PSP+6Ch */
} pblock;
/* parse the command name from the command line */
sp = prog;
while (*cmd && (*cmd != ' ') && (*cmd != '\t'))
*sp++ = *cmd++;
*sp = 0;
/* and parse out the command tail */
while (*cmd && ((*cmd == ' ') || (*cmd == '\t')))
++cmd;
*tail = (char) (strlen(cmd)); /* record the byte length */
strcpy(&tail[1], cmd);
strcat(&tail[1], "\r");
/* look up the program on the path trying various extentions */
if ((sp = flook(prog, TRUE)) == NULL)
if ((sp = flook(strcat(prog, ".exe"), TRUE)) == NULL) {
strcpy(&prog[strlen(prog) - 4], ".com");
if ((sp = flook(prog, TRUE)) == NULL)
return FALSE;
}
strcpy(prog, sp);
/* get a pointer to this PSPs environment segment number */
segread(&segreg);
/* set up the EXEC parameter block */
pblock.envptr = 0; /* make the child inherit the parents env */
pblock.fcb1 = f1; /* point to a blank FCB */
pblock.fcb2 = f2; /* point to a blank FCB */
pblock.cline = tail; /* parameter line pointer */
/* and make the call */
regs.h.ah = 0x4b; /* EXEC Load or Execute a Program */
regs.h.al = 0x00; /* load end execute function subcode */
segreg.ds = ((unsigned long) (prog) >> 16); /* program name ptr */
regs.x.dx = (unsigned int) (prog);
segreg.es = ((unsigned long) (&pblock) >> 16); /* set up param block ptr */
regs.x.bx = (unsigned int) (&pblock);
#if TURBO | MSC
intdosx(&regs, &regs, &segreg);
if (regs.x.cflag == 0) {
regs.h.ah = 0x4d; /* get child process return code */
intdos(&regs, &regs); /* go do it */
rval = regs.x.ax; /* save child's return code */
} else
#if MSC
rval = -1;
#else
rval = -_doserrno; /* failed child call */
#endif
#endif
return (rval < 0) ? FALSE : TRUE;
}
#endif

25
spawn.h
View File

@ -1,18 +1,11 @@
/* spawn.h -- various operating system access commands */ int spawncli( int f, int n) ;
#ifndef _SPAWN_H_ int bktoshell( int f, int n) ;
#define _SPAWN_H_
#include "names.h" /* BINDABLE() */
/* Bindable functions */
BINDABLE( spawncli) ;
BINDABLE( bktoshell) ;
BINDABLE( spawn) ;
BINDABLE( execprg) ;
BINDABLE( pipecmd) ;
BINDABLE( filter_buffer) ;
void rtfrmshell( void) ; void rtfrmshell( void) ;
int spawn( int f, int n) ;
int execprg( int f, int n) ;
int pipecmd( int f, int n) ;
int filter_buffer( int f, int n) ;
int sys( char *cmd) ;
int shellprog( char *cmd) ;
int execprog( char *cmd) ;
#endif
/* end of spawn.h */

176
tcap.c
View File

@ -1,7 +1,9 @@
/* tcap.c -- implements terminal.h */ /* tcap.c -- implements terminal.h */
#include "terminal.h" #include "terminal.h"
/* Unix V7 SysV and BS4 Termcap video driver /* tcap.c
*
* Unix V7 SysV and BS4 Termcap video driver
* *
* modified by Petri Kutvonen * modified by Petri Kutvonen
*/ */
@ -17,11 +19,13 @@
#define USE_BROKEN_OPTIMIZATION 0 #define USE_BROKEN_OPTIMIZATION 0
#define termdef 1 /* Don't define "term" external. */ #define termdef 1 /* Don't define "term" external. */
#ifndef MINGW32
#include <curses.h> #include <curses.h>
#include <term.h> #include <term.h>
#endif
#include "defines.h"
#include "display.h" #include "display.h"
#include "estruct.h"
#include "termio.h" #include "termio.h"
#if TERMCAP #if TERMCAP
@ -33,9 +37,9 @@ boolean sgarbf = TRUE ; /* TRUE if screen is garbage */
char sres[ 16] ; /* current screen resolution */ char sres[ 16] ; /* current screen resolution */
/* NORMAL, CGA, EGA, VGA */ /* NORMAL, CGA, EGA, VGA */
# if UNIX #if UNIX
# include <signal.h> #include <signal.h>
# endif #endif
#define MARGIN 8 #define MARGIN 8
#define SCRSIZ 64 #define SCRSIZ 64
@ -55,38 +59,36 @@ static void tcapscrollregion(int top, int bot);
static void putpad(char *str); static void putpad(char *str);
static void tcapopen(void); static void tcapopen(void);
# if PKCODE #if PKCODE
static void tcapclose(void); static void tcapclose(void);
# endif #endif
# if COLOR #if COLOR
static void tcapfcol(void); static void tcapfcol(void);
static void tcapbcol(void); static void tcapbcol(void);
# endif #endif
# if SCROLLCODE #if SCROLLCODE
static void tcapscroll_reg(int from, int to, int linestoscroll); static void tcapscroll_reg(int from, int to, int linestoscroll);
static void tcapscroll_delins(int from, int to, int linestoscroll); static void tcapscroll_delins(int from, int to, int linestoscroll);
# endif #endif
#define TCAPSLEN 315 #define TCAPSLEN 315
static char tcapbuf[TCAPSLEN]; static char tcapbuf[TCAPSLEN];
static char *_UP, _PC, *CM, *CE, *CL, *SO, *SE; static char *UP, PC, *CM, *CE, *CL, *SO, *SE;
# if PKCODE #if PKCODE
static char *TI, *TE; static char *TI, *TE;
# if USE_BROKEN_OPTIMIZATION #if USE_BROKEN_OPTIMIZATION
static int term_init_ok = 0; static int term_init_ok = 0;
# endif #endif
# endif #endif
# if SCROLLCODE #if SCROLLCODE
static char *CS, *DL, *AL, *SF, *SR; static char *CS, *DL, *AL, *SF, *SR;
# endif #endif
terminal_t term = { struct terminal term = {
480, /* actual 479 on 2560x1440 landscape terminal window */ 0, /* These four values are set dynamically at open time. */
2550, /* actual 2541 */
0, /* These four values are set dynamically at open time. */
0, 0,
0, 0,
0, 0,
@ -94,11 +96,11 @@ terminal_t term = {
SCRSIZ, SCRSIZ,
NPAUSE, NPAUSE,
tcapopen, tcapopen,
# if PKCODE #if PKCODE
tcapclose, tcapclose,
# else #else
ttclose, ttclose,
# endif #endif
tcapkopen, tcapkopen,
tcapkclose, tcapkclose,
ttgetc, ttgetc,
@ -110,14 +112,14 @@ terminal_t term = {
tcapbeep, tcapbeep,
tcaprev, tcaprev,
tcapcres tcapcres
# if COLOR #if COLOR
, tcapfcol, , tcapfcol,
tcapbcol tcapbcol
# endif #endif
# if SCROLLCODE #if SCROLLCODE
, NULL /* set dynamically at open time */ , NULL /* set dynamically at open time */
# endif #endif
} ; };
static void tcapopen(void) static void tcapopen(void)
{ {
@ -126,9 +128,9 @@ static void tcapopen(void)
char *tv_stype; char *tv_stype;
int int_col, int_row; int int_col, int_row;
# if PKCODE && USE_BROKEN_OPTIMIZATION #if PKCODE && USE_BROKEN_OPTIMIZATION
if (!term_init_ok) { if (!term_init_ok) {
# endif #endif
if ((tv_stype = getenv("TERM")) == NULL) { if ((tv_stype = getenv("TERM")) == NULL) {
fputs( "Environment variable TERM not defined!\n", stderr) ; fputs( "Environment variable TERM not defined!\n", stderr) ;
exit( EXIT_FAILURE) ; exit( EXIT_FAILURE) ;
@ -142,40 +144,50 @@ static void tcapopen(void)
} }
/* Get screen size from system, or else from termcap. */ /* Get screen size from system, or else from termcap. */
getscreensize( &int_col, &int_row) ; getscreensize(&int_col, &int_row);
if( (int_row <= 0) term.t_nrow = int_row - 1;
&& ((int_row = tgetnum("li")) == -1)) { term.t_ncol = int_col;
if ((term.t_nrow <= 0)
&& (term.t_nrow = (short) tgetnum("li") - 1) == -1) {
fputs( "termcap entry incomplete (lines)\n", stderr) ; fputs( "termcap entry incomplete (lines)\n", stderr) ;
exit( EXIT_FAILURE) ; exit( EXIT_FAILURE) ;
} }
if( (int_col <= 0) if ((term.t_ncol <= 0)
&& ((int_col = tgetnum("co")) == -1)) { && (term.t_ncol = (short) tgetnum("co")) == -1) {
fputs( "Termcap entry incomplete (columns)\n", stderr) ; fputs( "Termcap entry incomplete (columns)\n", stderr) ;
exit( EXIT_FAILURE) ; exit( EXIT_FAILURE) ;
} }
#ifdef SIGWINCH
/* At initialization we use maximum size even if current OS window is smaller */
term.t_mrow = MAXROW ;
term.t_mcol = MAXCOL ;
if( term.t_nrow >= term.t_mrow)
term.t_nrow = term.t_mrow - 1 ;
term.t_mrow = int_row < term.t_maxrow ? int_row : term.t_maxrow ; if( term.t_ncol > term.t_mcol)
term.t_nrow = term.t_mrow - 1 ; term.t_ncol = term.t_mcol ;
term.t_mcol = int_col < term.t_maxcol ? int_col : term.t_maxcol ; #else
term.t_ncol = term.t_mcol ; term.t_mrow = term.t_nrow > MAXROW ? MAXROW : term.t_nrow;
term.t_mcol = term.t_ncol > MAXCOL ? MAXCOL : term.t_ncol;
#endif
p = tcapbuf; p = tcapbuf;
t = tgetstr("pc", &p); t = tgetstr("pc", &p);
if (t) if (t)
_PC = *t; PC = *t;
else else
_PC = 0; PC = 0;
CL = tgetstr("cl", &p); CL = tgetstr("cl", &p);
CM = tgetstr("cm", &p); CM = tgetstr("cm", &p);
CE = tgetstr("ce", &p); CE = tgetstr("ce", &p);
_UP = tgetstr("up", &p); UP = tgetstr("up", &p);
SE = tgetstr("se", &p); SE = tgetstr("se", &p);
SO = tgetstr("so", &p); SO = tgetstr("so", &p);
if (SO != NULL) if (SO != NULL)
revexist = TRUE; revexist = TRUE;
# if PKCODE #if PKCODE
if (tgetnum("sg") > 0) { /* can reverse be used? P.K. */ if (tgetnum("sg") > 0) { /* can reverse be used? P.K. */
revexist = FALSE; revexist = FALSE;
SE = NULL; SE = NULL;
@ -183,16 +195,16 @@ static void tcapopen(void)
} }
TI = tgetstr("ti", &p); /* terminal init and exit */ TI = tgetstr("ti", &p); /* terminal init and exit */
TE = tgetstr("te", &p); TE = tgetstr("te", &p);
# endif #endif
if (CL == NULL || CM == NULL || _UP == NULL) { if (CL == NULL || CM == NULL || UP == NULL) {
fputs( "Incomplete termcap entry\n", stderr) ; fputs( "Incomplete termcap entry\n", stderr) ;
exit( EXIT_FAILURE) ; exit( EXIT_FAILURE) ;
} }
if (CE == NULL) /* will we be able to use clear to EOL? */ if (CE == NULL) /* will we be able to use clear to EOL? */
eolexist = FALSE; eolexist = FALSE;
# if SCROLLCODE #if SCROLLCODE
CS = tgetstr("cs", &p); CS = tgetstr("cs", &p);
SF = tgetstr("sf", &p); SF = tgetstr("sf", &p);
SR = tgetstr("sr", &p); SR = tgetstr("sr", &p);
@ -208,20 +220,20 @@ static void tcapopen(void)
} else { } else {
term.t_scroll = NULL; term.t_scroll = NULL;
} }
# endif #endif
if (p >= &tcapbuf[TCAPSLEN]) { if (p >= &tcapbuf[TCAPSLEN]) {
fputs( "Terminal description too big!\n", stderr) ; fputs( "Terminal description too big!\n", stderr) ;
exit( EXIT_FAILURE) ; exit( EXIT_FAILURE) ;
} }
# if PKCODE && USE_BROKEN_OPTIMIZATION #if PKCODE && USE_BROKEN_OPTIMIZATION
term_init_ok = 1; term_init_ok = 1;
} }
# endif #endif
ttopen(); ttopen();
} }
# if PKCODE #if PKCODE
static void tcapclose(void) static void tcapclose(void)
{ {
putpad(tgoto(CM, 0, term.t_nrow)); putpad(tgoto(CM, 0, term.t_nrow));
@ -229,24 +241,26 @@ static void tcapclose(void)
ttflush(); ttflush();
ttclose(); ttclose();
} }
# endif #endif
static void tcapkopen( void) { static void tcapkopen(void)
# if PKCODE {
putpad( TI) ; #if PKCODE
ttflush() ; putpad(TI);
ttrow = ttcol = -1 ; ttflush();
sgarbf = TRUE ; ttrow = 999;
# endif ttcol = 999;
strcpy(sres, "NORMAL") ; sgarbf = TRUE;
#endif
strcpy(sres, "NORMAL");
} }
static void tcapkclose(void) static void tcapkclose(void)
{ {
# if PKCODE #if PKCODE
putpad(TE); putpad(TE);
ttflush(); ttflush();
# endif #endif
} }
static void tcapmove(int row, int col) static void tcapmove(int row, int col)
@ -284,7 +298,7 @@ static int tcapcres(char *res)
return TRUE; return TRUE;
} }
# if SCROLLCODE #if SCROLLCODE
/* move howmanylines lines starting at from to to */ /* move howmanylines lines starting at from to to */
static void tcapscroll_reg(int from, int to, int howmanylines) static void tcapscroll_reg(int from, int to, int howmanylines)
@ -332,13 +346,13 @@ static void tcapscroll_delins(int from, int to, int howmanylines)
/* cs is set up just like cm, so we use tgoto... */ /* cs is set up just like cm, so we use tgoto... */
static void tcapscrollregion(int top, int bot) static void tcapscrollregion(int top, int bot)
{ {
ttputc(_PC); ttputc(PC);
putpad(tgoto(CS, bot, top)); putpad(tgoto(CS, bot, top));
} }
# endif #endif
# if COLOR #if COLOR
/* No colors here, ignore this. */ /* No colors here, ignore this. */
static void tcapfcol(void) static void tcapfcol(void)
{ {
@ -347,7 +361,7 @@ static void tcapfcol(void)
static void tcapbcol(void) static void tcapbcol(void)
{ {
} }
# endif #endif
static void tcapbeep(void) static void tcapbeep(void)
{ {
@ -356,8 +370,6 @@ static void tcapbeep(void)
static void putpad(char *str) static void putpad(char *str)
{ {
tputs( str, 1, (int (*)( int)) ttputc) ; tputs(str, 1, ttputc);
} }
#endif /* TERMCAP */ #endif /* TERMCAP */
/* end of tcap.c */

View File

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

270
termio.c
View File

@ -1,19 +1,21 @@
/* termio.c -- implements termio.h */ /* termio.c -- implements termio.h */
#if !defined( POSIX) && !defined( MINGW32)
#include "termio.h" #include "termio.h"
#include "defines.h" /* POSIX */ /* TERMIO.C
#ifndef POSIX *
* The functions in this file negotiate with the operating system for
/* The functions in this file negotiate with the operating system for * characters, and write characters in a barely buffered fashion on the display.
characters, and write characters in a barely buffered fashion on the * All operating systems.
display. All operating systems. *
* modified by Petri Kutvonen
modified by Petri Kutvonen
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "estruct.h"
#include "retcode.h" #include "retcode.h"
#include "utf8.h" #include "utf8.h"
@ -21,9 +23,35 @@
#include <unistd.h> #include <unistd.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
int ttrow = -1 ; /* Row location of HW cursor */ int ttrow = HUGE ; /* Row location of HW cursor */
int ttcol = -1 ; /* Column location of HW cursor */ int ttcol = HUGE ; /* Column location of HW cursor */
#if VMS
#include <stsdef.h>
#include <ssdef.h>
#include <descrip.h>
#include <iodef.h>
#include <ttdef.h>
#include <tt2def.h>
#define NIBUF 128 /* Input buffer size */
#define NOBUF 1024 /* MM says bug buffers win! */
#define EFN 0 /* Event flag */
char obuf[NOBUF]; /* Output buffer */
int nobuf; /* # of bytes in above */
char ibuf[NIBUF]; /* Input buffer */
int nibuf; /* # of bytes in above */
int ibufi; /* Read index */
int oldmode[3]; /* Old TTY mode bits */
int newmode[3]; /* New TTY mode bits */
short iochan; /* TTY I/O channel */
#endif
#if MSDOS & (MSC | TURBO)
union REGS rg; /* cpu register for use of DOS calls */
int nxtchar = -1; /* character held from type ahead */
#endif
#if USG /* System V */ #if USG /* System V */
#include <signal.h> #include <signal.h>
@ -40,7 +68,7 @@ static struct termio ntermio ; /* characteristics to use inside */
#endif #endif
#endif #endif
#if BSD #if V7 | BSD
#include <sgtty.h> /* for stty/gtty functions */ #include <sgtty.h> /* for stty/gtty functions */
#include <signal.h> #include <signal.h>
struct sgttyb ostate; /* saved tty state */ struct sgttyb ostate; /* saved tty state */
@ -70,7 +98,7 @@ char tobuf[TBUFSIZ]; /* terminal output buffer */
#endif #endif
#endif #endif
#if SVR4 #if __hpux | SVR4
extern int rtfrmshell(); /* return from suspended shell */ extern int rtfrmshell(); /* return from suspended shell */
#define TBUFSIZ 128 #define TBUFSIZ 128
char tobuf[TBUFSIZ]; /* terminal output buffer */ char tobuf[TBUFSIZ]; /* terminal output buffer */
@ -78,10 +106,68 @@ char tobuf[TBUFSIZ]; /* terminal output buffer */
/* /*
* This function is called once to set up the terminal device streams. * This function is called once to set up the terminal device streams.
* On CPM it is a no-op. * On VMS, it translates TT until it finds the terminal, then assigns
* a channel to it and sets it raw. On CPM it is a no-op.
*/ */
void ttopen(void) void ttopen(void)
{ {
#if VMS
struct dsc$descriptor idsc;
struct dsc$descriptor odsc;
char oname[40];
int iosb[2];
int status;
odsc.dsc$a_pointer = "TT";
odsc.dsc$w_length = strlen(odsc.dsc$a_pointer);
odsc.dsc$b_dtype = DSC$K_DTYPE_T;
odsc.dsc$b_class = DSC$K_CLASS_S;
idsc.dsc$b_dtype = DSC$K_DTYPE_T;
idsc.dsc$b_class = DSC$K_CLASS_S;
do {
idsc.dsc$a_pointer = odsc.dsc$a_pointer;
idsc.dsc$w_length = odsc.dsc$w_length;
odsc.dsc$a_pointer = &oname[0];
odsc.dsc$w_length = sizeof(oname);
status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
if (status != SS$_NORMAL && status != SS$_NOTRAN)
exit(status);
if (oname[0] == 0x1B) {
odsc.dsc$a_pointer += 4;
odsc.dsc$w_length -= 4;
}
} while (status == SS$_NORMAL);
status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
if (status != SS$_NORMAL)
exit(status);
status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
oldmode, sizeof(oldmode), 0, 0, 0, 0);
if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL)
exit(status);
newmode[0] = oldmode[0];
newmode[1] = oldmode[1] | TT$M_NOECHO;
#if XONXOFF
#else
newmode[1] &= ~(TT$M_TTSYNC | TT$M_HOSTSYNC);
#endif
newmode[2] = oldmode[2] | TT2$M_PASTHRU;
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
newmode, sizeof(newmode), 0, 0, 0, 0);
if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL)
exit(status);
term.t_nrow = (newmode[1] >> 24) - 1;
term.t_ncol = newmode[0] >> 16;
#endif
#if MSDOS & (TURBO | (PKCODE & MSC))
/* kill the CONTROL-break interupt */
rg.h.ah = 0x33; /* control-break check dos call */
rg.h.al = 1; /* set the current state */
rg.h.dl = 0; /* set it OFF */
intdos(&rg, &rg); /* go for it! */
#endif
#if USG #if USG
ioctl(0, TCGETA, &otermio); /* save old settings */ ioctl(0, TCGETA, &otermio); /* save old settings */
ntermio.c_iflag = 0; /* setup new settings */ ntermio.c_iflag = 0; /* setup new settings */
@ -103,7 +189,7 @@ void ttopen(void)
kbdpoll = FALSE; kbdpoll = FALSE;
#endif #endif
#if BSD #if V7 | BSD
gtty(0, &ostate); /* save old state */ gtty(0, &ostate); /* save old state */
gtty(0, &nstate); /* get base of new state */ gtty(0, &nstate); /* get base of new state */
#if XONXOFF #if XONXOFF
@ -128,27 +214,49 @@ void ttopen(void)
#endif #endif
#endif #endif
#if SVR4 #if __hpux | SVR4
/* provide a smaller terminal output buffer so that /* provide a smaller terminal output buffer so that
the type ahead detection works better (more often) */ the type ahead detection works better (more often) */
setvbuf(stdout, &tobuf[0], _IOFBF, TBUFSIZ); setvbuf(stdout, &tobuf[0], _IOFBF, TBUFSIZ);
signal(SIGTSTP, SIG_DFL); /* set signals so that we can */ signal(SIGTSTP, SIG_DFL); /* set signals so that we can */
signal(SIGCONT, rtfrmshell); /* suspend & restart emacs */ signal(SIGCONT, rtfrmshell); /* suspend & restart emacs */
TTflush(); TTflush();
#endif #endif /* __hpux */
/* on all screens we are not sure of the initial position /* on all screens we are not sure of the initial position
of the cursor */ of the cursor */
ttrow = ttcol = -1 ; ttrow = 999;
ttcol = 999;
} }
/* /*
* This function gets called just before we go back home to the command * This function gets called just before we go back home to the command
* interpreter. * interpreter. On VMS it puts the terminal back in a reasonable state.
* Another no-operation on CPM. * Another no-operation on CPM.
*/ */
void ttclose(void) void ttclose(void)
{ {
#if VMS
int status;
int iosb[1];
ttflush();
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
oldmode, sizeof(oldmode), 0, 0, 0, 0);
if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL)
exit(status);
status = SYS$DASSGN(iochan);
if (status != SS$_NORMAL)
exit(status);
#endif
#if MSDOS & (TURBO | (PKCODE & MSC))
/* restore the CONTROL-break interupt */
rg.h.ah = 0x33; /* control-break check dos call */
rg.h.al = 1; /* set the current state */
rg.h.dl = 1; /* set it ON */
intdos(&rg, &rg); /* go for it! */
#endif
#if USG #if USG
#if PKCODE #if PKCODE
ioctl(0, TCSETAW, &otermio); /* restore terminal settings */ ioctl(0, TCSETAW, &otermio); /* restore terminal settings */
@ -158,7 +266,7 @@ void ttclose(void)
fcntl(0, F_SETFL, kbdflgs); fcntl(0, F_SETFL, kbdflgs);
#endif #endif
#if BSD #if V7 | BSD
stty(0, &ostate); stty(0, &ostate);
ioctl(0, TIOCSETC, &otchars); /* Place old character into K */ ioctl(0, TIOCSETC, &otchars); /* Place old character into K */
#if BSD & PKCODE #if BSD & PKCODE
@ -168,15 +276,30 @@ void ttclose(void)
} }
/* /*
* Write a character to the display. * Write a character to the display. On VMS, terminal output is buffered, and
* we just put the characters in the big array, after checking for overflow.
* On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
* MS-DOS (use the very very raw console output routine).
*/ */
int ttputc( unicode_t c) { int ttputc( int c) {
char utf8[ 4] ; #if VMS
int bytes ; if (nobuf >= NOBUF)
ttflush();
obuf[nobuf++] = c;
#endif
bytes = unicode_to_utf8( c, utf8) ; #if MSDOS & ~IBMPC
fwrite( utf8, 1, bytes, stdout) ; bdos(6, c, 0);
return 0 ; #endif
#if V7 | USG | BSD
char utf8[6];
int bytes;
bytes = unicode_to_utf8(c, utf8);
fwrite(utf8, 1, bytes, stdout);
#endif
return 0 ;
} }
/* /*
@ -184,7 +307,26 @@ int ttputc( unicode_t c) {
* up. A no-operation on systems where byte at a time terminal I/O is done. * up. A no-operation on systems where byte at a time terminal I/O is done.
*/ */
void ttflush( void) { void ttflush( void) {
#if USG | BSD #if VMS
int status;
int iosb[2];
status = SS$_NORMAL;
if (nobuf != 0) {
status =
SYS$QIOW(EFN, iochan, IO$_WRITELBLK | IO$M_NOFORMAT,
iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
if (status == SS$_NORMAL)
status = iosb[0] & 0xFFFF;
nobuf = 0;
}
return status;
#endif
#if MSDOS
#endif
#if V7 | USG | BSD
/* /*
* Add some terminal output success checking, sometimes an orphaned * Add some terminal output success checking, sometimes an orphaned
* process may be left looping on SunOS 4.1. * process may be left looping on SunOS 4.1.
@ -209,11 +351,60 @@ void ttflush( void) {
/* /*
* Read a character from the terminal, performing no editing and doing no echo * Read a character from the terminal, performing no editing and doing no echo
* at all. * at all. More complex in VMS that almost anyplace else, which figures. Very
* Very simple on CPM, because the system can do exactly what you want. * simple on CPM, because the system can do exactly what you want.
*/ */
int ttgetc( void) { int ttgetc( void) {
#if BSD #if VMS
int status;
int iosb[2];
int term[2];
while (ibufi >= nibuf) {
ibufi = 0;
term[0] = 0;
term[1] = 0;
status = SYS$QIOW(EFN, iochan, IO$_READLBLK | IO$M_TIMED,
iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
if (status != SS$_NORMAL)
exit(status);
status = iosb[0] & 0xFFFF;
if (status != SS$_NORMAL && status != SS$_TIMEOUT &&
status != SS$_DATAOVERUN)
exit(status);
nibuf = (iosb[0] >> 16) + (iosb[1] >> 16);
if (nibuf == 0) {
status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
iosb, 0, 0, ibuf, 1, 0, term, 0,
0);
if (status != SS$_NORMAL
|| (status = (iosb[0] & 0xFFFF)) != SS$_NORMAL)
if (status != SS$_DATAOVERUN)
exit(status);
nibuf = (iosb[0] >> 16) + (iosb[1] >> 16);
}
}
return ibuf[ibufi++] & 0xFF; /* Allow multinational */
#endif
#if MSDOS & (MSC | TURBO)
int c; /* character read */
/* if a char already is ready, return it */
if (nxtchar >= 0) {
c = nxtchar;
nxtchar = -1;
return c;
}
/* call the dos to get a char */
rg.h.ah = 7; /* dos Direct Console Input call */
intdos(&rg, &rg);
c = rg.h.al; /* grab the char */
return c & 255;
#endif
#if V7 | BSD
return 255 & fgetc(stdin); /* 8BIT P.K. */ return 255 & fgetc(stdin); /* 8BIT P.K. */
#endif #endif
@ -237,12 +428,23 @@ int ttgetc( void) {
int typahead( void) int typahead( void)
{ {
#if MSDOS & (MSC | TURBO)
if (kbhit() != 0)
return TRUE;
else
return FALSE;
#endif
#if BSD #if BSD
int x; /* holds # of pending chars */ int x; /* holds # of pending chars */
return (ioctl(0, FIONREAD, &x) < 0) ? 0 : x; return (ioctl(0, FIONREAD, &x) < 0) ? 0 : x;
#endif #endif
#if PKCODE & VMS
return ibufi < nibuf;
#endif
#if USG #if USG
if (!kbdqp) { if (!kbdqp) {
if (!kbdpoll && fcntl(0, F_SETFL, kbdflgs | O_NDELAY) < 0) if (!kbdpoll && fcntl(0, F_SETFL, kbdflgs | O_NDELAY) < 0)
@ -255,12 +457,10 @@ int typahead( void)
return kbdqp; return kbdqp;
#endif #endif
# if !UNIX #if !UNIX & !VMS & !MSDOS
return FALSE; return FALSE;
# endif #endif
} }
# endif #endif
#endif /* not POSIX */ #endif /* not POSIX */
/* end of termio.c */

View File

@ -1,20 +1,18 @@
/* termio.h -- */
#ifndef _TERMIO_H_ #ifndef _TERMIO_H_
#define _TERMIO_H_ #define _TERMIO_H_
#include "utf8.h" #define TYPEAH 1 /* type ahead causes update to be skipped */
#define TYPEAH 1 /* type ahead causes update to be skipped */ #define HUGE 1000 /* Huge number (for row/col) */
extern int ttrow ; /* Row location of HW cursor */ extern int ttrow ; /* Row location of HW cursor */
extern int ttcol ; /* Column location of HW cursor */ extern int ttcol ; /* Column location of HW cursor */
void ttopen( void) ; void ttopen( void) ;
void ttclose( void) ; void ttclose( void) ;
int ttputc( unicode_t c) ; int ttputc( int c) ;
void ttflush( void) ; void ttflush( void) ;
int ttgetc( void) ; int ttgetc( void) ;
int typahead( void) ; int typahead( void) ;
#endif #endif
/* end of termio.h */

View File

@ -28,14 +28,17 @@ insert-string 123456789012345678901234567890123456789012345678901234567890123456
next-line next-line
insert-string _________1_________2_________3_________4_________5_________6_________7_________8_________9_________0_________1_________2_________3 insert-string _________1_________2_________3_________4_________5_________6_________7_________8_________9_________0_________1_________2_________3
next-line next-line
; Create and insert string variable until size exceed 1024 characters or variable get truncated ; Create and insert string variable until size exceed string limit [will be truncated to NSTRING - 1 (127)
set %nam 123 set %nam 123
set %expect &len %nam set %expect &len %nam
!while &and &les %expect 1024 &equ &len %nam %expect !while &equ &len %nam %expect
insert-string %nam insert-string %nam
newline newline
set %nam &cat %nam %nam set %nam &cat %nam %nam
set %expect &tim %expect 2 set %expect &tim %expect 2
!if &not &les %expect 1024
!break
!endif
!endwhile !endwhile
insert-string %nam insert-string %nam
newline newline
@ -44,7 +47,6 @@ newline
insert-string &cat "Expected: " %expect insert-string &cat "Expected: " %expect
newline newline
; Use the variable as filename [will be truncated to NFILEN - 1 (79)] ; Use the variable as filename [will be truncated to NFILEN - 1 (79)]
set %nam &mid %nam 1 255
write-file %nam write-file %nam
insert-string &cat "Filename: " $cfname insert-string &cat "Filename: " $cfname
newline newline
@ -69,4 +71,3 @@ set-mark
end-of-file end-of-file
copy-region copy-region
insert-string $kill insert-string $kill
redraw-display

123
utf8.c
View File

@ -1,27 +1,11 @@
/* utf8.c -- implements utf8.h, conversion between unicode and UTF-8 */ /* utf8.c -- implements utf8.h, converts between unicode and UTF-8 */
#include "utf8.h" #include "utf8.h"
#include <assert.h> #include <assert.h>
#include <wchar.h> /* either _XOPEN_SOURCE or _GNU_SOURCE */
/*
/* Display width of UTF-8 character */ * utf8_to_unicode()
int _utf8_width( unicode_t c) {
#if __SIZEOF_WCHAR_T__ == 2 /* wcwidth only supports UTF-16 */
return (c < 0x10000) ? wcwidth( (wchar_t) c) : -1 ;
#else
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 */
}
/* utf8_to_unicode()
* *
* Convert a UTF-8 sequence to its unicode value, and return the length of * Convert a UTF-8 sequence to its unicode value, and return the length of
* the sequence in bytes. * the sequence in bytes.
@ -33,54 +17,66 @@ int utf8_width( unicode_t c) {
* NOTE 2! This does *not* verify things like minimality. So overlong forms * NOTE 2! This does *not* verify things like minimality. So overlong forms
* are happily accepted and decoded, as are the various "invalid values". * are happily accepted and decoded, as are the various "invalid values".
*/ */
unsigned utf8_to_unicode( const char *line, unsigned index, unsigned len, unsigned utf8_to_unicode(char *line, unsigned index, unsigned len, unicode_t *res)
unicode_t *res) { {
assert( index < len) ; unicode_t value ;
unsigned c = *res = (unsigned char) line[ index] ; unsigned c = line[ index] & 0xFFU ;
unsigned bytes, mask, i;
/* 0xxxxxxx is valid one byte utf8 *res = c;
/*
* 0xxxxxxx is valid one byte utf8
* 10xxxxxx is invalid UTF-8 start byte, we assume it is Latin1 * 10xxxxxx is invalid UTF-8 start byte, we assume it is Latin1
* 1100000x is start of overlong encoding sequence * 1100000x is start of overlong encoding sequence
* Sequence longer than 4 bytes are invalid * Sequence longer than 4 bytes are invalid
* Last valid code is 0x10FFFF, encoding start with 0xF4 * Last valid code is 0x10FFFF, encoding start with 0xF4
*/ */
if( c <= 0xC1 || c > 0xF4) if( c <= 0xC1 || c > 0xF4)
return 1 ; return 1;
/* Ok, it's 11xxxxxx, do a stupid decode */ /* Ok, it's 11xxxxxx, do a stupid decode */
unsigned mask = 0x20 ; mask = 0x20;
unsigned bytes = 2 ; bytes = 2;
while( (c & mask) != 0) { while( (c & mask) != 0) {
bytes++ ; bytes++;
mask >>= 1 ; mask >>= 1;
} }
/* bytes is in range [2..4] as c was in range [C2..F4] */ /* bytes is in range [2..4] as c was in range [C2..F4] */
len -= index ; len -= index;
if( bytes > len) if (bytes > len)
return 1 ; return 1;
unicode_t value = c & (mask - 1) ; value = c & (mask-1);
/* Ok, do the bytes */ /* Ok, do the bytes */
line += index ; line += index;
for( unsigned i = 2 ; i <= bytes ; i++) { for (i = 1; i < bytes; i++) {
c = (unsigned char) *++line ; c = line[i] & 0xFFU ;
if( (c & 0xc0) != 0x80) if ((c & 0xc0) != 0x80)
return 1 ; return 1;
value = (value << 6) | (c & 0x3f);
value = (value << 6) | (c & 0x3f) ;
} }
if( value > 0x10FFFF) /* Avoid 110000 - 13FFFF */ if( value > 0x10FFFF) /* Avoid 110000 - 13FFFF */
return 1 ; return 1 ;
*res = value ; *res = value;
return bytes ; return bytes;
} }
static void reverse_string(char *begin, char *end)
{
do {
char a = *begin, b = *end;
*end = a; *begin = b;
begin++; end--;
} while (begin < end);
}
/* unicode_to_utf8() /*
* unicode_to_utf8()
* *
* Convert a unicode value to its canonical utf-8 sequence. * Convert a unicode value to its canonical utf-8 sequence.
* *
@ -96,12 +92,12 @@ unsigned unicode_to_utf8( unicode_t c, char *utf8) {
assert( c <= 0x10FFFF) ; assert( c <= 0x10FFFF) ;
#ifdef NDEBUG #ifdef NDEBUG
if( c > 0x10FFFF) /* Let's assume this is due to sign extension */ if( c > 0x10FFFF) /* Let's assume this is due to sign extension */
c &= 0xFF ; c &= 0xFF ;
#endif #endif
if( c <= 0x7f) if( c <= 0x7f)
*utf8 = (char) c ; *utf8 = (char) c ;
else { else {
unsigned prefix = 0x40 ; unsigned prefix = 0x40 ;
char *p = utf8 ; char *p = utf8 ;
@ -112,39 +108,12 @@ unsigned unicode_to_utf8( unicode_t c, char *utf8) {
c >>= 6 ; c >>= 6 ;
} while( c >= prefix) ; } while( c >= prefix) ;
*p-- = *utf8 ; *p = (char) (c - 2 * prefix) ;
*utf8++ = (char) (c - 2 * prefix) ; reverse_string( utf8, p) ;
if( utf8 < p) { /* swap middle two bytes if 4 bytes utf-8 code */
char c = *p ;
*p = *utf8 ;
*utf8 = c ;
}
} }
return bytes ; return bytes ;
} }
unsigned utf8_revdelta( unsigned char *p, unsigned pos) {
unsigned delta = 0 ;
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 ;
}
}
return delta ;
}
/* end of utf8.c */ /* end of utf8.c */

11
utf8.h
View File

@ -1,15 +1,10 @@
/* utf8.h -- conversion between unicode and UTF-8 */ #ifndef UTF8_H
#ifndef _UTF8_H_ #define UTF8_H
#define _UTF8_H_
typedef unsigned int unicode_t ; typedef unsigned int unicode_t ;
int _utf8_width( unicode_t c) ; /* straight width */ unsigned utf8_to_unicode( char *line, unsigned index, unsigned len,
int utf8_width( unicode_t c) ; /* workaround width */
unsigned utf8_to_unicode( const char *line, unsigned index, unsigned len,
unicode_t *res) ; unicode_t *res) ;
unsigned utf8_revdelta( unsigned char *buf, unsigned pos) ;
unsigned unicode_to_utf8( unicode_t c, char *utf8) ; unsigned unicode_to_utf8( unicode_t c, char *utf8) ;
#endif #endif
/* end of utf8.h */

20
util.c
View File

@ -1,20 +0,0 @@
/* util.c -- implements util.h */
#include "util.h"
/* Safe zeroing, no complaining about overlap */
void mystrscpy( char *dst, const char *src, int size) {
if( size <= 0)
return ;
while( --size) {
char c = *src++ ;
if( !c)
break ;
*dst++ = c ;
}
*dst = 0 ;
}
/* end of util.c */

10
util.h
View File

@ -1,10 +0,0 @@
/* util.h -- utility functions */
#ifndef _UTIL_H_
#define _UTIL_H_
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
void mystrscpy( char *dst, const char *src, int size) ;
#endif
/* end of util.h */

View File

@ -1,18 +1,17 @@
/* version.h -- name and version strings */ #ifndef VERSION_H_
#ifndef _VERSION_H_ #define VERSION_H_
#define _VERSION_H_
#ifdef PROGRAM #ifdef PROGRAM
# define _QUOTE( s) #s # define _QUOTE( s) #s
# define QUOTE( s) _QUOTE( s) # define QUOTE( s) _QUOTE( s)
# define PROGRAM_NAME QUOTE(PROGRAM) # define PROGRAM_NAME QUOTE(PROGRAM)
#else #else
# define PROGRAM_NAME "ue" # define PROGRAM_NAME "em"
#endif #endif
#define PROGRAM_NAME_UTF8 "µEMACS" # define PROGRAM_NAME_PFX "\xC2"
# define PROGRAM_NAME_LONG "\xB5""EMACS" /* UTF-8 µEMACS */
#define VERSION "4.2.5" # define VERSION "4.2.1"
#endif #endif /* VERSION_H_ */
/* end of version.h */

436
window.c
View File

@ -1,66 +1,76 @@
/* window.c -- inplements window.h */ /* window.c -- inplements window.h */
#include "window.h" #include "window.h"
/* Window management. Some of the functions are internal, and some are /* window.c
attached to keys that the user actually types. *
* Window management. Some of the functions are internal, and some are
* attached to keys that the user actually types.
*
*/ */
#include <assert.h> #include <stdio.h>
#include <stdlib.h> /* malloc(), free() */
#include "basic.h" #include "basic.h"
#include "buffer.h" #include "buffer.h"
#include "defines.h" #include "display.h"
#include "display.h" /* upmode() */ #include "estruct.h"
#include "execute.h" #include "execute.h"
#include "line.h" #include "line.h"
#include "mlout.h"
#include "terminal.h" #include "terminal.h"
#include "wrapper.h" #include "wrapper.h"
window_p curwp ; /* Current window */
window_p wheadp ; /* Head of list of windows */
static window_p savwindow = NULL ; /* saved window pointer */ struct window *curwp ; /* Current window */
struct window *wheadp ; /* Head of list of windows */
static struct window *swindow = NULL ; /* saved window pointer */
/* Reposition dot in the current window to line "n". If the argument is /*
positive, it is that line. If it is negative it is that line from the * Reposition dot in the current window to line "n". If the argument is
bottom. If it is 0 the window is centered (this is what the standard * positive, it is that line. If it is negative it is that line from the
redisplay code does). With no argument it defaults to 0. Bound to M-!. * bottom. If it is 0 the window is centered (this is what the standard
* redisplay code does). With no argument it defaults to 0. Bound to M-!.
*/ */
TBINDABLE( reposition) { int reposition(int f, int n)
curwp->w_force = (f == FALSE) ? 0 : n ; /* default to 0 to center screen */ {
curwp->w_flag |= WFFORCE ; if (f == FALSE) /* default to 0 to center screen */
return TRUE ; n = 0;
curwp->w_force = n;
curwp->w_flag |= WFFORCE;
return TRUE;
} }
/*
/* Refresh the screen. With no argument, it just does the refresh. With * Refresh the screen. With no argument, it just does the refresh. With an
an argument it recenters "." in the current window. Bound to "C-L". * argument it recenters "." in the current window. Bound to "C-L".
*/ */
TBINDABLE( redraw) { int redraw(int f, int n)
if( f == FALSE) {
sgarbf = TRUE ; if (f == FALSE)
sgarbf = TRUE;
else { else {
curwp->w_force = 0 ; /* Center dot. */ curwp->w_force = 0; /* Center dot. */
curwp->w_flag |= WFFORCE ; curwp->w_flag |= WFFORCE;
} }
return TRUE ; return TRUE;
} }
/*
/* The command make the next window (next => down the screen) the current * The command make the next window (next => down the screen) the current
window. There are no real errors, although the command does nothing if * window. There are no real errors, although the command does nothing if
there is only 1 window on the screen. Bound to "C-X O". * there is only 1 window on the screen. Bound to "C-X C-N".
*
with an argument this command finds the <n>th window from the top * with an argument this command finds the <n>th window from the top
*
int f, n; default flag and numeric argument * int f, n; default flag and numeric argument
*
*/ */
BINDABLE( nextwind) { int nextwind(int f, int n)
window_p wp; {
struct window *wp;
int nwindows; /* total number of windows */ int nwindows; /* total number of windows */
if (f) { if (f) {
@ -83,8 +93,10 @@ BINDABLE( nextwind) {
wp = wheadp; wp = wheadp;
while (--n) while (--n)
wp = wp->w_wndp; wp = wp->w_wndp;
} else } else {
return mloutfail( "Window number out of range") ; mlwrite("Window number out of range");
return FALSE;
}
} else if ((wp = curwp->w_wndp) == NULL) } else if ((wp = curwp->w_wndp) == NULL)
wp = wheadp; wp = wheadp;
curwp = wp; curwp = wp;
@ -94,14 +106,15 @@ BINDABLE( nextwind) {
return TRUE; return TRUE;
} }
/*
/* This command makes the previous window (previous => up the screen) the * This command makes the previous window (previous => up the screen) the
current window. There arn't any errors, although the command does not * current window. There arn't any errors, although the command does not do a
do a lot if there is 1 window. * lot if there is 1 window.
*/ */
BINDABLE( prevwind) { int prevwind(int f, int n)
window_p wp1; {
window_p wp2; struct window *wp1;
struct window *wp2;
/* if we have an argument, we mean the nth window from the bottom */ /* if we have an argument, we mean the nth window from the bottom */
if (f) if (f)
@ -123,26 +136,28 @@ BINDABLE( prevwind) {
return TRUE; return TRUE;
} }
/*
/* This command moves the current window down by "arg" lines. Recompute the * This command moves the current window down by "arg" lines. Recompute the
* top line in the window. The move up and move down code is almost completely * top line in the window. The move up and move down code is almost completely
* the same; most of the work has to do with reframing the window, and picking * the same; most of the work has to do with reframing the window, and picking
* a new dot. We share the code by having "move down" just be an interface to * a new dot. We share the code by having "move down" just be an interface to
* "move up". Magic. Bound to "C-X C-N". * "move up". Magic. Bound to "C-X C-N".
*/ */
BINDABLE( mvdnwind) { int mvdnwind(int f, int n)
return mvupwind( f, -n) ; {
return mvupwind(f, -n);
} }
/*
/* Move the current window up by "arg" lines. Recompute the new top line of * Move the current window up by "arg" lines. Recompute the new top line of
* the window. Look to see if "." is still on the screen. If it is, you win. * the window. Look to see if "." is still on the screen. If it is, you win.
* If it isn't, then move "." to center it in the new framing of the window * If it isn't, then move "." to center it in the new framing of the window
* (this command does not really move "."; it moves the frame). Bound to * (this command does not really move "."; it moves the frame). Bound to
* "C-X C-P". * "C-X C-P".
*/ */
BINDABLE( mvupwind) { int mvupwind(int f, int n)
line_p lp; {
struct line *lp;
int i; int i;
lp = curwp->w_linep; lp = curwp->w_linep;
@ -177,16 +192,17 @@ BINDABLE( mvupwind) {
return TRUE; return TRUE;
} }
/*
/* This command makes the current window the only window on the screen. Bound * This command makes the current window the only window on the screen. Bound
* to "C-X 1". Try to set the framing so that "." does not have to move on the * to "C-X 1". Try to set the framing so that "." does not have to move on the
* display. Some care has to be taken to keep the values of dot and mark in * display. Some care has to be taken to keep the values of dot and mark in
* the buffer structures right if the distruction of a window makes a buffer * the buffer structures right if the distruction of a window makes a buffer
* become undisplayed. * become undisplayed.
*/ */
BINDABLE( onlywind) { int onlywind(int f, int n)
window_p wp; {
line_p lp; struct window *wp;
struct line *lp;
int i; int i;
while (wheadp != curwp) { while (wheadp != curwp) {
@ -224,20 +240,23 @@ BINDABLE( onlywind) {
return TRUE; return TRUE;
} }
/*
/* Delete the current window, placing its space in the window above, * Delete the current window, placing its space in the window above,
* or, if it is the top window, the window below. Bound to C-X 0. * or, if it is the top window, the window below. Bound to C-X 0.
* *
* int f, n; arguments are ignored for this command * int f, n; arguments are ignored for this command
*/ */
BINDABLE( delwind) { int delwind(int f, int n)
window_p wp; /* window to recieve deleted space */ {
window_p lwp; /* ptr window before curwp */ struct window *wp; /* window to recieve deleted space */
struct window *lwp; /* ptr window before curwp */
int target; /* target line to search for */ int target; /* target line to search for */
/* if there is only one window, don't delete it */ /* if there is only one window, don't delete it */
if( wheadp->w_wndp == NULL) if (wheadp->w_wndp == NULL) {
return mloutfail( "Can not delete this window") ; mlwrite("Can not delete this window");
return FALSE;
}
/* find window before curwp in linked list */ /* find window before curwp in linked list */
wp = wheadp; wp = wheadp;
@ -296,8 +315,8 @@ BINDABLE( delwind) {
return TRUE; return TRUE;
} }
/*
/* Split the current window. A window smaller than 3 lines cannot be * Split the current window. A window smaller than 3 lines cannot be
* split. An argument of 1 forces the cursor into the upper window, an * split. An argument of 1 forces the cursor into the upper window, an
* argument of two forces the cursor to the lower window. The only * argument of two forces the cursor to the lower window. The only
* other error that is possible is a "malloc" failure allocating the * other error that is possible is a "malloc" failure allocating the
@ -305,24 +324,21 @@ BINDABLE( delwind) {
* *
* int f, n; default flag and numeric argument * int f, n; default flag and numeric argument
*/ */
BINDABLE( splitwind) { int splitwind(int f, int n)
window_p wp; {
line_p lp; struct window *wp;
struct line *lp;
int ntru; int ntru;
int ntrl; int ntrl;
int ntrd; int ntrd;
window_p wp1; struct window *wp1;
window_p wp2; struct window *wp2;
if( curwp->w_ntrows < 3) { if (curwp->w_ntrows < 3) {
mloutfmt( "Cannot split a %d line window", curwp->w_ntrows) ; mlwrite("Cannot split a %d line window", curwp->w_ntrows);
return FALSE ; return FALSE;
} }
wp = xmalloc(sizeof(struct window));
wp = malloc( sizeof *wp) ;
if( wp == NULL)
return mloutfail( "Out of memory") ;
++curbp->b_nwnd; /* Displayed twice. */ ++curbp->b_nwnd; /* Displayed twice. */
wp->w_bufp = curbp; wp->w_bufp = curbp;
wp->w_dotp = curwp->w_dotp; wp->w_dotp = curwp->w_dotp;
@ -381,30 +397,33 @@ BINDABLE( splitwind) {
return TRUE; return TRUE;
} }
/*
/* Enlarge the current window. Find the window that loses space. Make sure it * Enlarge the current window. Find the window that loses space. Make sure it
* is big enough. If so, hack the window descriptions, and ask redisplay to do * is big enough. If so, hack the window descriptions, and ask redisplay to do
* all the hard work. You don't just set "force reframe" because dot would * all the hard work. You don't just set "force reframe" because dot would
* move. Bound to "C-X Z". * move. Bound to "C-X Z".
*/ */
BINDABLE( enlargewind) { int enlargewind(int f, int n)
window_p adjwp; {
line_p lp; struct window *adjwp;
struct line *lp;
int i; int i;
if (n < 0) if (n < 0)
return shrinkwind(f, -n); return shrinkwind(f, -n);
if( wheadp->w_wndp == NULL) if (wheadp->w_wndp == NULL) {
return mloutfail( "Only one window") ; mlwrite("Only one window");
return FALSE;
}
if ((adjwp = curwp->w_wndp) == NULL) { if ((adjwp = curwp->w_wndp) == NULL) {
adjwp = wheadp; adjwp = wheadp;
while (adjwp->w_wndp != curwp) while (adjwp->w_wndp != curwp)
adjwp = adjwp->w_wndp; adjwp = adjwp->w_wndp;
} }
if( adjwp->w_ntrows <= n) if (adjwp->w_ntrows <= n) {
return mloutfail( "Impossible change") ; mlwrite("Impossible change");
return FALSE;
}
if (curwp->w_wndp == adjwp) { /* Shrink below. */ if (curwp->w_wndp == adjwp) { /* Shrink below. */
lp = adjwp->w_linep; lp = adjwp->w_linep;
for (i = 0; i < n && lp != adjwp->w_bufp->b_linep; ++i) for (i = 0; i < n && lp != adjwp->w_bufp->b_linep; ++i)
@ -430,29 +449,32 @@ BINDABLE( enlargewind) {
return TRUE; return TRUE;
} }
/*
/* Shrink the current window. Find the window that gains space. Hack at the * Shrink the current window. Find the window that gains space. Hack at the
* window descriptions. Ask the redisplay to do all the hard work. Bound to * window descriptions. Ask the redisplay to do all the hard work. Bound to
* "C-X C-Z". * "C-X C-Z".
*/ */
BINDABLE( shrinkwind) { int shrinkwind(int f, int n)
window_p adjwp; {
line_p lp; struct window *adjwp;
struct line *lp;
int i; int i;
if (n < 0) if (n < 0)
return enlargewind(f, -n); return enlargewind(f, -n);
if( wheadp->w_wndp == NULL) if (wheadp->w_wndp == NULL) {
return mloutfail( "Only one window") ; mlwrite("Only one window");
return FALSE;
}
if ((adjwp = curwp->w_wndp) == NULL) { if ((adjwp = curwp->w_wndp) == NULL) {
adjwp = wheadp; adjwp = wheadp;
while (adjwp->w_wndp != curwp) while (adjwp->w_wndp != curwp)
adjwp = adjwp->w_wndp; adjwp = adjwp->w_wndp;
} }
if( curwp->w_ntrows <= n) if (curwp->w_ntrows <= n) {
return mloutfail( "Impossible change") ; mlwrite("Impossible change");
return FALSE;
}
if (curwp->w_wndp == adjwp) { /* Grow below. */ if (curwp->w_wndp == adjwp) { /* Grow below. */
lp = adjwp->w_linep; lp = adjwp->w_linep;
for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_linep; for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_linep;
@ -479,12 +501,13 @@ BINDABLE( shrinkwind) {
return TRUE; return TRUE;
} }
/*
/* Resize the current window to the requested size * Resize the current window to the requested size
* *
* int f, n; default flag and numeric argument * int f, n; default flag and numeric argument
*/ */
BINDABLE( resize) { int resize(int f, int n)
{
int clines; /* current # of lines in window */ int clines; /* current # of lines in window */
/* must have a non-default argument, else ignore call */ /* must have a non-default argument, else ignore call */
@ -501,14 +524,14 @@ BINDABLE( resize) {
return enlargewind(TRUE, n - clines); return enlargewind(TRUE, n - clines);
} }
/*
/* Pick a window for a pop-up. Split the screen if there is only one window. * Pick a window for a pop-up. Split the screen if there is only one window.
* Pick the uppermost window that isn't the current window. An LRU algorithm * Pick the uppermost window that isn't the current window. An LRU algorithm
* might be better. Return a pointer, or NULL on error. * might be better. Return a pointer, or NULL on error.
*/ */
window_p wpopup(void) struct window *wpopup(void)
{ {
window_p wp; struct window *wp;
if (wheadp->w_wndp == NULL /* Only 1 window */ if (wheadp->w_wndp == NULL /* Only 1 window */
&& splitwind(FALSE, 0) == FALSE) /* and it won't split */ && splitwind(FALSE, 0) == FALSE) /* and it won't split */
@ -519,159 +542,176 @@ window_p wpopup(void)
return wp; return wp;
} }
int scrnextup(int f, int n)
/* scroll the next window up (back) a page */ { /* scroll the next window up (back) a page */
BINDABLE( scrnextup) {
nextwind(FALSE, 1); nextwind(FALSE, 1);
backpage(f, n); backpage(f, n);
prevwind(FALSE, 1); prevwind(FALSE, 1);
return TRUE; return TRUE;
} }
int scrnextdw(int f, int n)
/* scroll the next window down (forward) a page */ { /* scroll the next window down (forward) a page */
BINDABLE( scrnextdw) {
nextwind(FALSE, 1); nextwind(FALSE, 1);
forwpage(f, n); forwpage(f, n);
prevwind(FALSE, 1); prevwind(FALSE, 1);
return TRUE; return TRUE;
} }
int savewnd(int f, int n)
/* save ptr to current window */ { /* save ptr to current window */
BINDABLE( savewnd) { swindow = curwp;
savwindow = curwp ; return TRUE;
return TRUE ;
} }
int restwnd(int f, int n)
{ /* restore the saved screen */
struct window *wp;
/* restore the saved screen */ /* find the window */
BINDABLE( restwnd) { wp = wheadp;
/* check the saved window still exists */ while (wp != NULL) {
for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) { if (wp == swindow) {
if( wp == savwindow) { curwp = wp;
curwp = wp ; curbp = wp->w_bufp;
curbp = wp->w_bufp ; upmode();
upmode() ; return TRUE;
return TRUE ;
} }
wp = wp->w_wndp;
} }
return mloutfail( "(No such window exists)") ; mlwrite("(No such window exists)");
return FALSE;
} }
/*
static void adjust( window_p wp, int screenrows) { * resize the screen, re-writing the screen
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 f; default flag
* int n; numeric argument * int n; numeric argument
*/ */
BBINDABLE( newsize) { int newsize(int f, int n)
window_p wp ; /* current window being examined */ {
struct window *wp; /* current window being examined */
struct window *nextwp; /* next window to scan */
struct window *lastwp; /* last window scanned */
int lastline; /* screen line of last line of current window */
/* if the command defaults, assume the largest */ /* if the command defaults, assume the largest */
if( f == FALSE) if (f == FALSE)
n = term.t_mrow ; n = term.t_mrow ;
/* make sure it's in range */ /* make sure it's in range */
if( n < MINROWS || n > term.t_mrow) if (n < 3 || n > term.t_mrow) {
return mloutfail( "%%Screen size out of range") ; mlwrite("%%Screen size out of range");
return FALSE;
}
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 */ /* go to the last window */
for( wp = wheadp ; wp->w_wndp != NULL ; wp = wp->w_wndp) wp = wheadp;
; while (wp->w_wndp != NULL)
wp = wp->w_wndp;
/* and enlarge it as needed */ /* and enlarge it as needed */
adjust( wp, n) ; wp->w_ntrows = n - wp->w_toprow - 2;
} else { wp->w_flag |= WFHARD | WFMODE;
/* new size is smaller */
/* rebuild the window structure */
assert( wheadp->w_toprow == 0) ; /* proves coverity wrong */
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 */ } else {
if( wp->w_toprow == n - 2)
adjust( lastwp, n) ; /* rebuild the window structure */
nextwp = wheadp;
wp = NULL;
lastwp = NULL;
while (nextwp != NULL) {
wp = nextwp;
nextwp = wp->w_wndp;
/* get rid of it if it is too low */ /* get rid of it if it is too low */
if( wp->w_toprow >= n - 2) { if (wp->w_toprow > n - 2) {
/* save the point/mark if needed */ /* save the point/mark if needed */
if( --wp->w_bufp->b_nwnd == 0) { if (--wp->w_bufp->b_nwnd == 0) {
wp->w_bufp->b_dotp = wp->w_dotp ; wp->w_bufp->b_dotp = wp->w_dotp;
wp->w_bufp->b_doto = wp->w_doto ; wp->w_bufp->b_doto = wp->w_doto;
wp->w_bufp->b_markp = wp->w_markp ; wp->w_bufp->b_markp = wp->w_markp;
wp->w_bufp->b_marko = wp->w_marko ; wp->w_bufp->b_marko = wp->w_marko;
} }
/* update curwp and lastwp if needed */ /* update curwp and lastwp if needed */
if( wp == curwp) { if (wp == curwp)
curwp = wheadp ; curwp = wheadp;
curbp = curwp->w_bufp ; curbp = curwp->w_bufp;
} if (lastwp != NULL)
lastwp->w_wndp = NULL;
/* free the structure */ /* free the structure */
free( wp) ; free((char *) wp);
lastwp->w_wndp = NULL ; wp = NULL;
} else {
/* need to change this window size? */
if( (wp->w_toprow + wp->w_ntrows - 1) >= n - 2)
adjust( wp, n) ;
lastwp = wp ; } 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;
}
} }
lastwp = wp;
} }
} }
/* screen is garbage */ /* screen is garbage */
term.t_nrow = n - 1 ; term.t_nrow = n - 1;
sgarbf = TRUE ; sgarbf = TRUE;
return TRUE ; return TRUE;
} }
/*
/* resize the screen, re-writing the screen * resize the screen, re-writing the screen
* *
* int f; default flag * int f; default flag
* int n; numeric argument * int n; numeric argument
*/ */
BBINDABLE( newwidth) { int newwidth(int f, int n)
{
struct window *wp;
/* if the command defaults, assume the largest */ /* if the command defaults, assume the largest */
if( f == FALSE) if (f == FALSE)
n = term.t_mcol ; n = term.t_mcol;
/* make sure it's in range */ /* make sure it's in range */
if( n < MINCOLS || n > term.t_mcol) if (n < 10 || n > term.t_mcol) {
return mloutfail( "%%Screen width out of range") ; mlwrite("%%Screen width out of range");
return FALSE;
}
/* otherwise, just re-width it (no big deal) */ /* otherwise, just re-width it (no big deal) */
term.t_ncol = n ; term.t_ncol = n;
updmargin() ; term.t_margin = n / 10;
term.t_scrsiz = n - (term.t_margin * 2);
/* force all windows to redraw */ /* florce all windows to redraw */
for( window_p wp = wheadp ; wp; wp = wp->w_wndp) wp = wheadp;
wp->w_flag |= WFHARD | WFMOVE | WFMODE ; while (wp) {
wp->w_flag |= WFHARD | WFMOVE | WFMODE;
wp = wp->w_wndp;
}
sgarbf = TRUE;
sgarbf = TRUE ; return TRUE;
return TRUE ;
} }
int getwpos(void) int getwpos(void)
{ /* get screen offset of current line in current window */ { /* get screen offset of current line in current window */
int sline; /* screen line from top of window */ int sline; /* screen line from top of window */
line_p lp; /* scannile line pointer */ struct line *lp; /* scannile line pointer */
/* search down the line we want */ /* search down the line we want */
lp = curwp->w_linep; lp = curwp->w_linep;
@ -689,5 +729,3 @@ void cknewwindow(void)
{ {
execute(META | SPEC | 'X', FALSE, 1); execute(META | SPEC | 'X', FALSE, 1);
} }
/* end of window.c */

117
window.h
View File

@ -1,78 +1,71 @@
/* window.h -- window functionality */
#ifndef _WINDOW_H_ #ifndef _WINDOW_H_
#define _WINDOW_H_ #define _WINDOW_H_
#include "defines.h" /* COLOR, SCROLLCODE */ #include "defines.h" /* COLOR, SCROLLCODE */
#include "buffer.h" /* buffer_p, line_p */ #include "buffer.h" /* buffer, line */
#include "names.h" /* BINDABLE() */
/* There is a window structure allocated for every active display window. /*
The windows are kept in a big list, in top to bottom screen order, with * There is a window structure allocated for every active display window. The
the listhead at "wheadp". Each window contains its own values of dot * windows are kept in a big list, in top to bottom screen order, with the
and mark. The flag field contains some bits that are set by commands to * listhead at "wheadp". Each window contains its own values of dot and mark.
guide redisplay. Although this is a bit of a compromise in terms of * The flag field contains some bits that are set by commands to guide
decoupling, the full blown redisplay is just too expensive to run for * redisplay. Although this is a bit of a compromise in terms of decoupling,
every input character. * the full blown redisplay is just too expensive to run for every input
* character.
*/ */
typedef struct window { struct window {
struct window *w_wndp; /* Next window */ struct window *w_wndp; /* Next window */
buffer_p w_bufp ; /* Buffer displayed in window */ struct buffer *w_bufp; /* Buffer displayed in window */
line_p w_linep ; /* Top line in the window */ struct line *w_linep; /* Top line in the window */
line_p w_dotp ; /* Line containing "." */ struct line *w_dotp; /* Line containing "." */
line_p w_markp ; /* Line containing "mark" */ struct line *w_markp; /* Line containing "mark" */
int w_doto ; /* Byte offset for "." */ int w_doto; /* Byte offset for "." */
int w_marko ; /* Byte offset for "mark" */ int w_marko; /* Byte offset for "mark" */
int w_toprow ; /* Origin 0 top row of window */ int w_toprow ; /* Origin 0 top row of window */
int w_ntrows ; /* # of rows of text in window */ int w_ntrows ; /* # of rows of text in window */
char w_force ; /* If NZ, forcing row. */ char w_force; /* If NZ, forcing row. */
char w_flag ; /* Flags. */ char w_flag; /* Flags. */
#if COLOR #if COLOR
char w_fcolor ; /* current forground color */ char w_fcolor; /* current forground color */
char w_bcolor ; /* current background color */ char w_bcolor; /* current background color */
#endif #endif
} *window_p ; };
extern window_p curwp ; /* Current window */ extern struct window *curwp ; /* Current window */
extern window_p wheadp ; /* Head of list of windows */ extern struct window *wheadp ; /* Head of list of windows */
/* curwbyte return the byte after the dot in current window */ #define WFFORCE 0x01 /* Window needs forced reframe */
#define curwbyte() lgetc( curwp->w_dotp, curwp->w_doto) #define WFMOVE 0x02 /* Movement from line to line */
#define WFEDIT 0x04 /* Editing within a line */
#define WFFORCE 0x01 /* Window needs forced reframe */ #define WFHARD 0x08 /* Better to a full display */
#define WFMOVE 0x02 /* Movement from line to line */ #define WFMODE 0x10 /* Update mode line. */
#define WFEDIT 0x04 /* Editing within a line */ #define WFCOLR 0x20 /* Needs a color change */
#define WFHARD 0x08 /* Better to a full display */
#define WFMODE 0x10 /* Update mode line. */
#define WFCOLR 0x20 /* Needs a color change */
#if SCROLLCODE #if SCROLLCODE
# define WFKILLS 0x40 /* something was deleted */ #define WFKILLS 0x40 /* something was deleted */
# define WFINS 0x80 /* something was inserted */ #define WFINS 0x80 /* something was inserted */
#endif #endif
/* Bindable functions */ int reposition( int f, int n);
BINDABLE( delwind) ; int redraw( int f, int n) ;
BINDABLE( enlargewind) ; int nextwind( int f, int n) ;
BINDABLE( mvdnwind) ; int prevwind( int f, int n) ;
BINDABLE( mvupwind) ; int mvdnwind( int f, int n) ;
BBINDABLE( newsize) ; int mvupwind( int f, int n) ;
BBINDABLE( newwidth) ; int onlywind( int f, int n) ;
BINDABLE( nextwind) ; int delwind( int f, int n) ;
BINDABLE( onlywind) ; int splitwind( int f, int n) ;
BINDABLE( prevwind) ; int enlargewind( int f, int n) ;
TBINDABLE( redraw) ; int shrinkwind( int f, int n) ;
TBINDABLE( reposition) ; int resize( int f, int n) ;
BINDABLE( resize) ; int scrnextup( int f, int n) ;
BINDABLE( restwnd) ; int scrnextdw( int f, int n) ;
BINDABLE( savewnd) ; int savewnd( int f, int n) ;
BINDABLE( scrnextdw) ; int restwnd( int f, int n) ;
BINDABLE( scrnextup) ; int newsize( int f, int n) ;
BINDABLE( shrinkwind) ; int newwidth( int f, int n) ;
BINDABLE( splitwind) ;
int getwpos( void) ; int getwpos( void) ;
void cknewwindow( void) ; void cknewwindow( void) ;
window_p wpopup( void) ; /* Pop up window creation. */ struct window *wpopup( void) ; /* Pop up window creation. */
#endif #endif
/* end of window.h */

717
word.c
View File

@ -1,46 +1,46 @@
/* word.c -- implements word.h */ /* word.c -- implements word.h */
#include "word.h" #include "word.h"
/* The routines in this file implement commands that work word or a /* word.c
paragraph at a time. There are all sorts of word mode commands. If I *
do any sentence mode commands, they are likely to be put in this file. * The routines in this file implement commands that work word or a
* paragraph at a time. There are all sorts of word mode commands. If I
Modified by Petri Kutvonen * do any sentence mode commands, they are likely to be put in this file.
*
* Modified by Petri Kutvonen
*/ */
#include <assert.h> #include <stdio.h>
#include <stdlib.h> /* malloc, free */
#include <string.h> /* memcpy */
#include "basic.h" #include "basic.h"
#include "buffer.h" #include "buffer.h"
#include "defines.h" #include "estruct.h"
#include "isa.h"
#include "line.h" #include "line.h"
#include "mlout.h" #include "mlout.h"
#include "random.h" #include "random.h"
#include "region.h" #include "region.h"
#include "window.h" #include "window.h"
#define ALLOCSZ 32
#define TAB 0x09 /* a tab character */ #define TAB 0x09 /* a tab character */
#if PKCODE
static int justflag = FALSE ; /* justify, don't fill */ static int justflag = FALSE ; /* justify, don't fill */
#endif
static int inword( void) ; static int inword( void) ;
/* Word wrap on n-spaces. Back-over whatever precedes the point on the /* Word wrap on n-spaces. Back-over whatever precedes the point on the current
current line and stop on the first word-break or the beginning of the * line and stop on the first word-break or the beginning of the line. If we
line. If we reach the beginning of the line, jump back to the end of * reach the beginning of the line, jump back to the end of the word and start
the word and start a new line. Otherwise, break the line at the * a new line. Otherwise, break the line at the word-break, eat it, and jump
word-break, eat it, and jump back to the end of the word. * back to the end of the word.
* Returns TRUE on success, FALSE on errors.
Returns TRUE on success, FALSE on errors. *
* @f: default flag.
@f: default flag. * @n: numeric argument.
@n: numeric argument.
*/ */
BINDABLE( wrapword) { int wrapword(int f, int n)
{
int cnt; /* size of word wrapped to next line */ int cnt; /* size of word wrapped to next line */
int c; /* charector temporary */ int c; /* charector temporary */
@ -79,140 +79,192 @@ BINDABLE( wrapword) {
return TRUE; return TRUE;
} }
/*
/* Move the cursor backward by "n" words. All of the details of motion are * Move the cursor backward by "n" words. All of the details of motion are
performed by the "backchar" and "forwchar" routines. Error if you try * performed by the "backchar" and "forwchar" routines. Error if you try to
to move beyond the buffers. * move beyond the buffers.
*/ */
BINDABLE( backword) { int backword(int f, int n)
if( n < 0) {
return forwword( f, -n) ; if (n < 0)
return forwword(f, -n);
if( backchar( FALSE, 1) == FALSE) if (backchar(FALSE, 1) == FALSE)
return FALSE ; return FALSE;
while (n--) {
while( n--) { while (inword() == FALSE) {
while( !inword()) if (backchar(FALSE, 1) == FALSE)
if( backchar( FALSE, 1) == FALSE) return FALSE;
return FALSE ; }
while (inword() != FALSE) {
do { if (backchar(FALSE, 1) == FALSE)
if( backchar( FALSE, 1) == FALSE) return FALSE;
return FALSE ; }
} while( inword()) ;
} }
return forwchar(FALSE, 1);
return forwchar( FALSE, 1) ;
} }
/*
/* Move the cursor forward by the specified number of words. All of the * Move the cursor forward by the specified number of words. All of the motion
motion is done by "forwchar". Error if you try and move beyond the * is done by "forwchar". Error if you try and move beyond the buffer's end.
buffer's end.
*/ */
BINDABLE( forwword) { int forwword(int f, int n)
if( n < 0) {
return backword( f, -n) ; if (n < 0)
return backword(f, -n);
while (n--) {
while (inword() == TRUE) {
if (forwchar(FALSE, 1) == FALSE)
return FALSE;
}
while( n--) { while (inword() == FALSE) {
while( inword()) if (forwchar(FALSE, 1) == FALSE)
if( forwchar( FALSE, 1) == FALSE) return FALSE;
return FALSE ; }
do {
if( forwchar( FALSE, 1) == FALSE)
return FALSE ;
} while( !inword()) ;
} }
return TRUE;
return TRUE ;
} }
/* Word capitalize, to upper and to lower /*
*/ * Move the cursor forward by the specified number of words. As you move,
static boolean uniflip( boolean toupper_f) { /* flip unicode case and forward */ * convert any characters to upper case. Error if you try and move beyond the
unicode_t c ; * end of the buffer. Bound to "M-U".
int len ; */
int upperword(int f, int n)
{
int c;
len = lgetchar( &c) ; /* len => unicode or extended ASCII */ if (curbp->b_mode & MDVIEW) /* don't allow this command if */
if( (c <= 255) && ( toupper_f ? islower( c) : isupper( c))) { return rdonly(); /* we are in read only mode */
c = flipcase( c) ; if (n < 0)
ldelchar( 1, FALSE) ; return FALSE;
if( len == 1) while (n--) {
linsert_byte( 1, c) ; while (inword() == FALSE) {
else if (forwchar(FALSE, 1) == FALSE)
linsert( 1, c) ; return FALSE;
}
lchange( WFHARD) ; while (inword() != FALSE) {
} else c = lgetc(curwp->w_dotp, curwp->w_doto);
if( forwchar( FALSE, 1) == FALSE) #if PKCODE
return FALSE ; if (islower(c)) {
#else
return TRUE ; if (c >= 'a' && c <= 'z') {
} #endif
c -= 'a' - 'A';
static boolean capcapword( int n, boolean first_f, boolean rest_f) { lputc(curwp->w_dotp, curwp->w_doto, c);
assert( !(curbp->b_mode & MDVIEW)) ; lchange(WFHARD);
}
if( n < 0) if (forwchar(FALSE, 1) == FALSE)
return FALSE ; return FALSE;
}
while( n--) {
while( !inword())
if( forwchar( FALSE, 1) == FALSE)
return FALSE ;
if( !uniflip( first_f))
return FALSE ;
while( inword())
if( !uniflip( rest_f))
return FALSE ;
} }
return TRUE;
return TRUE ;
} }
/*
/* Move the cursor forward by the specified number of words. As you move, * Move the cursor forward by the specified number of words. As you move
convert any characters to upper case. Error if you try and move beyond * convert characters to lower case. Error if you try and move over the end of
the end of the buffer. Bound to "M-U". * the buffer. Bound to "M-L".
*/ */
BINDABLE( upperword) { int lowerword(int f, int n)
return capcapword( n, TRUE, TRUE) ; {
int c;
if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return rdonly(); /* we are in read only mode */
if (n < 0)
return FALSE;
while (n--) {
while (inword() == FALSE) {
if (forwchar(FALSE, 1) == FALSE)
return FALSE;
}
while (inword() != FALSE) {
c = lgetc(curwp->w_dotp, curwp->w_doto);
#if PKCODE
if (isupper(c)) {
#else
if (c >= 'A' && c <= 'Z') {
#endif
c += 'a' - 'A';
lputc(curwp->w_dotp, curwp->w_doto, c);
lchange(WFHARD);
}
if (forwchar(FALSE, 1) == FALSE)
return FALSE;
}
}
return TRUE;
} }
/*
/* Move the cursor forward by the specified number of words. As you move * Move the cursor forward by the specified number of words. As you move
convert characters to lower case. Error if you try and move over the * convert the first character of the word to upper case, and subsequent
end of the buffer. Bound to "M-L". * characters to lower case. Error if you try and move past the end of the
* buffer. Bound to "M-C".
*/ */
BINDABLE( lowerword) { int capword(int f, int n)
return capcapword( n, FALSE, FALSE) ; {
int c;
if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return rdonly(); /* we are in read only mode */
if (n < 0)
return FALSE;
while (n--) {
while (inword() == FALSE) {
if (forwchar(FALSE, 1) == FALSE)
return FALSE;
}
if (inword() != FALSE) {
c = lgetc(curwp->w_dotp, curwp->w_doto);
#if PKCODE
if (islower(c)) {
#else
if (c >= 'a' && c <= 'z') {
#endif
c -= 'a' - 'A';
lputc(curwp->w_dotp, curwp->w_doto, c);
lchange(WFHARD);
}
if (forwchar(FALSE, 1) == FALSE)
return FALSE;
while (inword() != FALSE) {
c = lgetc(curwp->w_dotp, curwp->w_doto);
#if PKCODE
if (isupper(c)) {
#else
if (c >= 'A' && c <= 'Z') {
#endif
c += 'a' - 'A';
lputc(curwp->w_dotp, curwp->w_doto,
c);
lchange(WFHARD);
}
if (forwchar(FALSE, 1) == FALSE)
return FALSE;
}
}
}
return TRUE;
} }
/*
/* Move the cursor forward by the specified number of words. As you move * Kill forward by "n" words. Remember the location of dot. Move forward by
convert the first character of the word to upper case, and subsequent * the right number of words. Put dot back where it was and issue the kill
characters to lower case. Error if you try and move past the end of the * command for the right number of characters. With a zero argument, just
buffer. Bound to "M-C". * kill one word and no whitespace. Bound to "M-D".
*/ */
BINDABLE( capword) { int delfword(int f, int n)
return capcapword( n, TRUE, FALSE) ; {
} struct line *dotp; /* original cursor line */
/* Kill forward by "n" words. Remember the location of dot. Move forward
by the right number of words. Put dot back where it was and issue the
kill command for the right number of characters. With a zero argument,
just kill one word and no whitespace. Bound to "M-D".
*/
BINDABLE( delfword) {
line_p dotp; /* original cursor line */
int doto; /* and row */ int doto; /* and row */
int c; /* temp char */ int c; /* temp char */
long size; /* # of chars to delete */
assert( !(curbp->b_mode & MDVIEW)) ; /* don't allow this command if we are in read only mode */
if (curbp->b_mode & MDVIEW)
return rdonly();
/* ignore the command if there is a negative argument */ /* ignore the command if there is a negative argument */
if (n < 0) if (n < 0)
@ -228,7 +280,7 @@ BINDABLE( delfword) {
doto = curwp->w_doto; doto = curwp->w_doto;
/* figure out how many characters to give the axe */ /* figure out how many characters to give the axe */
long size = 0 ; size = 0;
/* get us into a word.... */ /* get us into a word.... */
while (inword() == FALSE) { while (inword() == FALSE) {
@ -287,14 +339,18 @@ BINDABLE( delfword) {
return ldelete(size, TRUE); return ldelete(size, TRUE);
} }
/*
/* Kill backwards by "n" words. Move backwards by the desired number of * Kill backwards by "n" words. Move backwards by the desired number of words,
words, counting the characters. When dot is finally moved to its * counting the characters. When dot is finally moved to its resting place,
resting place, fire off the kill command. Bound to "M-Rubout" and to * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
"M-Backspace".
*/ */
BINDABLE( delbword) { int delbword(int f, int n)
assert( !(curbp->b_mode & MDVIEW)) ; {
long size;
/* don't allow this command if we are in read only mode */
if (curbp->b_mode & MDVIEW)
return rdonly();
/* ignore the command if there is a nonpositive argument */ /* ignore the command if there is a nonpositive argument */
if (n <= 0) if (n <= 0)
@ -307,8 +363,7 @@ BINDABLE( delbword) {
if (backchar(FALSE, 1) == FALSE) if (backchar(FALSE, 1) == FALSE)
return FALSE; return FALSE;
size = 0;
long size = 0 ;
while (n--) { while (n--) {
while (inword() == FALSE) { while (inword() == FALSE) {
if (backchar(FALSE, 1) == FALSE) if (backchar(FALSE, 1) == FALSE)
@ -330,70 +385,72 @@ BINDABLE( delbword) {
* Return TRUE if the character at dot is a character that is considered to be * Return TRUE if the character at dot is a character that is considered to be
* part of a word. The word character list is hard coded. Should be setable. * part of a word. The word character list is hard coded. Should be setable.
*/ */
static int inword( void) { static int inword(void)
{
int c; int c;
if( curwp->w_doto == llength( curwp->w_dotp)) if (curwp->w_doto == llength(curwp->w_dotp))
return FALSE ; return FALSE;
c = lgetc(curwp->w_dotp, curwp->w_doto);
c = lgetc( curwp->w_dotp, curwp->w_doto) ; #if PKCODE
return isletter( c) || ( c >= '0' && c <= '9') ; if (isletter(c))
#else
if (c >= 'a' && c <= 'z')
return TRUE;
if (c >= 'A' && c <= 'Z')
#endif
return TRUE;
if (c >= '0' && c <= '9')
return TRUE;
return FALSE;
} }
static int parafillnjustify( int f, int n, int justify_f) { #if WORDPRO
unicode_t c; /* current char during scan */ /*
unicode_t *wbuf ; /* buffer for current word */ * Fill the current paragraph according to the current
int wbufsize ; * fill column
*
* f and n - deFault flag and Numeric argument
*/
int fillpara(int f, int n)
{
unicode_t c; /* current char during scan */
unicode_t wbuf[NSTRING];/* buffer for current word */
int wordlen; /* length of current word */ int wordlen; /* length of current word */
int clength; /* position on line during fill */ int clength; /* position on line during fill */
int i; /* index during word copy */
int newlength; /* tentative new line length */
int eopflag; /* Are we at the End-Of-Paragraph? */ int eopflag; /* Are we at the End-Of-Paragraph? */
int firstflag = TRUE ; /* first word? (needs no space) */ int firstflag; /* first word? (needs no space) */
line_p eopline; /* pointer to line just past EOP */ struct line *eopline; /* pointer to line just past EOP */
int dotflag = 0 ; /* was the last char a period? */ int dotflag; /* was the last char a period? */
int leftmarg = 0 ; /* left marginal */
assert( !(curbp->b_mode & MDVIEW)) ; if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return rdonly(); /* we are in read only mode */
if( fillcol == 0) /* no fill column set */ if (fillcol == 0) { /* no fill column set */
return mloutfail( "No fill column set") ; mloutstr( "No fill column set") ;
return FALSE;
if( justify_f) {
leftmarg = getccol( FALSE) ;
if( leftmarg + 10 > fillcol)
return mloutfail( "Column too narrow") ;
justflag = justify_f ;
}
wbufsize = ALLOCSZ ;
wbuf = malloc( ALLOCSZ * sizeof *wbuf) ;
if( NULL == wbuf) {
justflag = FALSE ;
return FALSE ;
} }
#if PKCODE
justflag = FALSE;
#endif
/* record the pointer to the line just past the EOP */ /* record the pointer to the line just past the EOP */
gotoeop(FALSE, 1); gotoeop(FALSE, 1);
eopline = lforw(curwp->w_dotp); eopline = lforw(curwp->w_dotp);
/* and back to the beginning of the paragraph */ /* and back top the beginning of the paragraph */
gotobop(FALSE, 1); gotobop(FALSE, 1);
/* initialize various info */ /* initialize various info */
if( justflag && leftmarg < llength(curwp->w_dotp)) { clength = curwp->w_doto;
setccol( leftmarg) ; if (clength && curwp->w_dotp->l_text[0] == TAB)
lgetchar( &c) ; clength = 8;
if( c == ' ' || c == '\t')
/* on a space */
if( getccol( TRUE) < getccol( FALSE))
/* first non space before current position */
firstflag = FALSE ;
}
clength = getccol( FALSE) ;
wordlen = 0; wordlen = 0;
dotflag = FALSE;
/* scan through lines, filling words */ /* scan through lines, filling words */
firstflag = TRUE;
eopflag = FALSE; eopflag = FALSE;
while (!eopflag) { while (!eopflag) {
int bytes = 1; int bytes = 1;
@ -411,92 +468,165 @@ static int parafillnjustify( int f, int n, int justify_f) {
/* if not a separator, just add it in */ /* if not a separator, just add it in */
if (c != ' ' && c != '\t') { if (c != ' ' && c != '\t') {
if (wordlen < wbufsize) dotflag = (c == '.'); /* was it a dot */
if (wordlen < NSTRING - 1)
wbuf[wordlen++] = c; wbuf[wordlen++] = c;
else {
/* overflow */
unicode_t *newptr ;
newptr = realloc( wbuf, (wbufsize + ALLOCSZ) * sizeof *wbuf) ;
if( newptr != NULL) {
wbuf = newptr ;
wbufsize += ALLOCSZ ;
wbuf[ wordlen++] = c ;
} /* else the word is truncated silently */
}
} else if (wordlen) { } else if (wordlen) {
/* at a word break with a word waiting */ /* at a word break with a word waiting */
if( firstflag) /* calculate tentitive new length with word added */
firstflag = FALSE ; newlength = clength + 1 + wordlen;
else { if (newlength <= fillcol) {
/* calculate tentative new length with word added */
if( fillcol > clength + dotflag + 1 + wordlen) {
/* add word to current line */ /* add word to current line */
linsert( dotflag + 1, ' ') ; /* the space */ if (!firstflag) {
clength += dotflag + 1 ; linsert(1, ' '); /* the space */
} else { ++clength;
/* start a new line */
lnewline();
linsert( leftmarg, ' ') ;
clength = leftmarg;
} }
firstflag = FALSE;
} else {
/* start a new line */
lnewline();
clength = 0;
} }
/* and add the word in in either case */ /* and add the word in in either case */
for( int i = 0 ; i < wordlen ; i++) { for (i = 0; i < wordlen; i++) {
c = wbuf[ i] ; linsert(1, wbuf[i]);
linsert( 1, c) ; ++clength;
}
if (dotflag) {
linsert(1, ' ');
++clength; ++clength;
} }
dotflag = c == '.' ; /* was the last char a period? */
wordlen = 0; wordlen = 0;
} }
} }
/* and add a last newline for the end of our new paragraph */ /* and add a last newline for the end of our new paragraph */
if( eopline == curbp->b_linep) /* at EOF? */ lnewline();
forwchar( FALSE, 1) ;
else
lnewline() ;
if( justflag) {
forwword(FALSE, 1);
setccol( leftmarg) ;
justflag = FALSE;
}
free( wbuf) ;
return TRUE; return TRUE;
} }
#if PKCODE
/* Fill the current paragraph according to the current
* fill column
*
* f and n - deFault flag and Numeric argument
*/
BINDABLE( fillpara) {
return parafillnjustify( f, n, FALSE) ;
}
/* Fill the current paragraph according to the current /* Fill the current paragraph according to the current
* fill column and cursor position * fill column and cursor position
* *
* int f, n; deFault flag and Numeric argument * int f, n; deFault flag and Numeric argument
*/ */
BINDABLE( justpara) { int justpara(int f, int n)
return parafillnjustify( f, n, TRUE) ; {
unicode_t c; /* current char durring scan */
unicode_t wbuf[NSTRING];/* buffer for current word */
int wordlen; /* length of current word */
int clength; /* position on line during fill */
int i; /* index during word copy */
int newlength; /* tentative new line length */
int eopflag; /* Are we at the End-Of-Paragraph? */
int firstflag; /* first word? (needs no space) */
struct line *eopline; /* pointer to line just past EOP */
int leftmarg; /* left marginal */
if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return rdonly(); /* we are in read only mode */
if (fillcol == 0) { /* no fill column set */
mloutstr( "No fill column set") ;
return FALSE;
}
justflag = TRUE;
leftmarg = curwp->w_doto;
if (leftmarg + 10 > fillcol) {
leftmarg = 0;
mloutstr( "Column too narrow") ;
return FALSE;
}
/* record the pointer to the line just past the EOP */
gotoeop(FALSE, 1);
eopline = lforw(curwp->w_dotp);
/* and back top the beginning of the paragraph */
gotobop(FALSE, 1);
/* initialize various info */
if (leftmarg < llength(curwp->w_dotp))
curwp->w_doto = leftmarg;
clength = curwp->w_doto;
if (clength && curwp->w_dotp->l_text[0] == TAB)
clength = 8;
wordlen = 0;
/* scan through lines, filling words */
firstflag = TRUE;
eopflag = FALSE;
while (!eopflag) {
int bytes = 1;
/* get the next character in the paragraph */
if (curwp->w_doto == llength(curwp->w_dotp)) {
c = ' ';
if (lforw(curwp->w_dotp) == eopline)
eopflag = TRUE;
} else
bytes = lgetchar(&c);
/* and then delete it */
ldelete(bytes, FALSE);
/* if not a separator, just add it in */
if (c != ' ' && c != '\t') {
if (wordlen < NSTRING - 1)
wbuf[wordlen++] = c;
} else if (wordlen) {
/* at a word break with a word waiting */
/* calculate tentitive new length with word added */
newlength = clength + 1 + wordlen;
if (newlength <= fillcol) {
/* add word to current line */
if (!firstflag) {
linsert(1, ' '); /* the space */
++clength;
}
firstflag = FALSE;
} else {
/* start a new line */
lnewline();
for (i = 0; i < leftmarg; i++)
linsert(1, ' ');
clength = leftmarg;
}
/* and add the word in in either case */
for (i = 0; i < wordlen; i++) {
linsert(1, wbuf[i]);
++clength;
}
wordlen = 0;
}
}
/* and add a last newline for the end of our new paragraph */
lnewline();
forwword(FALSE, 1);
if (llength(curwp->w_dotp) > leftmarg)
curwp->w_doto = leftmarg;
else
curwp->w_doto = llength(curwp->w_dotp);
justflag = FALSE;
return TRUE;
} }
#endif
/*
/* delete n paragraphs starting with the current one * delete n paragraphs starting with the current one
* *
* int f default flag * int f default flag
* int n # of paras to delete * int n # of paras to delete
*/ */
BINDABLE( killpara) { int killpara(int f, int n)
{
int status; /* returned status of functions */
while (n--) { /* for each paragraph to delete */ while (n--) { /* for each paragraph to delete */
/* mark out the end and beginning of the para to delete */ /* mark out the end and beginning of the para to delete */
@ -511,26 +641,26 @@ BINDABLE( killpara) {
curwp->w_doto = 0; /* force us to the beginning of line */ curwp->w_doto = 0; /* force us to the beginning of line */
/* and delete it */ /* and delete it */
int status = killregion( FALSE, 1) ; if ((status = killregion(FALSE, 1)) != TRUE)
if( status != TRUE) return status;
return status ;
/* and clean up the 2 extra lines */ /* and clean up the 2 extra lines */
ldelete(2L, TRUE); ldelete(2L, TRUE);
} }
return TRUE;
return TRUE ;
} }
/* wordcount: count the # of words in the marked region, /*
* wordcount: count the # of words in the marked region,
* along with average word sizes, # of chars, etc, * along with average word sizes, # of chars, etc,
* and report on them. * and report on them.
* *
* int f, n; ignored numeric arguments * int f, n; ignored numeric arguments
*/ */
BINDABLE( wordcount) { int wordcount(int f, int n)
line_p lp; /* current line to scan */ {
struct line *lp; /* current line to scan */
int offset; /* current char to scan */ int offset; /* current char to scan */
long size; /* size of region left to count */ long size; /* size of region left to count */
int ch; /* current character to scan */ int ch; /* current character to scan */
@ -541,10 +671,10 @@ BINDABLE( wordcount) {
int nlines; /* total number of lines in region */ int nlines; /* total number of lines in region */
int avgch; /* average number of chars/word */ int avgch; /* average number of chars/word */
int status; /* status return code */ int status; /* status return code */
region_t region ; /* region to look at */ struct region region; /* region to look at */
/* make sure we have a region to count */ /* make sure we have a region to count */
if( (status = getregion( &region)) != TRUE) if ((status = getregion(&region)) != TRUE)
return status; return status;
lp = region.r_linep; lp = region.r_linep;
offset = region.r_offset; offset = region.r_offset;
@ -569,7 +699,14 @@ BINDABLE( wordcount) {
} }
/* and tabulate it */ /* and tabulate it */
wordflag = isletter( ch) || (ch >= '0' && ch <= '9') ; wordflag = (
#if PKCODE
(isletter(ch)) ||
#else
(ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
#endif
(ch >= '0' && ch <= '9'));
if (wordflag == TRUE && lastword == FALSE) if (wordflag == TRUE && lastword == FALSE)
++nwords; ++nwords;
lastword = wordflag; lastword = wordflag;
@ -586,82 +723,104 @@ BINDABLE( wordcount) {
nwords, nchars, nlines + 1, avgch) ; nwords, nchars, nlines + 1, avgch) ;
return TRUE; return TRUE;
} }
#endif
#if WORDPRO
/* go back to the beginning of the current paragraph /*
* go back to the beginning of the current paragraph
* here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE> * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
* combination to delimit the beginning of a paragraph * combination to delimit the beginning of a paragraph
* *
* int f, n; default Flag & Numeric argument * int f, n; default Flag & Numeric argument
*/ */
BINDABLE( gotobop) { int gotobop(int f, int n)
{
int suc; /* success of last backchar */
if (n < 0) /* the other way... */ if (n < 0) /* the other way... */
return gotoeop(f, -n); return gotoeop(f, -n);
while (n-- > 0) { /* for each one asked for */ while (n-- > 0) { /* for each one asked for */
/* first scan back until we are in a word */ /* first scan back until we are in a word */
while( backchar( FALSE, 1) && !inword()) ; suc = backchar(FALSE, 1);
while (!inword() && suc)
suc = backchar(FALSE, 1);
curwp->w_doto = 0; /* and go to the B-O-Line */ curwp->w_doto = 0; /* and go to the B-O-Line */
/* and scan back until we hit a <NL><NL> or <NL><TAB> /* and scan back until we hit a <NL><NL> or <NL><TAB>
or a <NL><SPACE> */ or a <NL><SPACE> */
while (lback(curwp->w_dotp) != curbp->b_linep) while (lback(curwp->w_dotp) != curbp->b_linep)
if (llength(curwp->w_dotp) != 0 && if (llength(curwp->w_dotp) != 0 &&
#if PKCODE
((justflag == TRUE) || ((justflag == TRUE) ||
#endif
(lgetc(curwp->w_dotp, curwp->w_doto) != TAB && (lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
lgetc(curwp->w_dotp, curwp->w_doto) != ' ')) lgetc(curwp->w_dotp, curwp->w_doto) != ' '))
#if PKCODE
) )
#endif
curwp->w_dotp = lback(curwp->w_dotp); curwp->w_dotp = lback(curwp->w_dotp);
else else
break; break;
/* and then forward until we are in a word */ /* and then forward until we are in a word */
while( !inword() && forwchar( FALSE, 1)) ; suc = forwchar(FALSE, 1);
while (suc && !inword())
suc = forwchar(FALSE, 1);
} }
curwp->w_flag |= WFMOVE; /* force screen update */ curwp->w_flag |= WFMOVE; /* force screen update */
return TRUE; return TRUE;
} }
/*
/* Go forward to the end of the current paragraph here we look for a * Go forword to the end of the current paragraph
<NL><NL> or <NL><TAB> or <NL><SPACE> combination to delimit the * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
beginning of a paragraph * combination to delimit the beginning of a paragraph
*
int f, n; default Flag & Numeric argument * int f, n; default Flag & Numeric argument
*/ */
BINDABLE( gotoeop) { int gotoeop(int f, int n)
{
int suc; /* success of last backchar */
if (n < 0) /* the other way... */ if (n < 0) /* the other way... */
return gotobop(f, -n); return gotobop(f, -n);
while (n-- > 0) { /* for each one asked for */ while (n-- > 0) { /* for each one asked for */
/* first scan forward until we are in a word */ /* first scan forward until we are in a word */
while( !inword() && forwchar( FALSE, 1)) ; suc = forwchar(FALSE, 1);
curwp->w_doto = 0 ; /* and go to the B-O-Line */ while (!inword() && suc)
if( curwp->w_dotp != curbp->b_linep) /* of next line if not at EOF */ suc = forwchar(FALSE, 1);
curwp->w_dotp = lforw( curwp->w_dotp) ; curwp->w_doto = 0; /* and go to the B-O-Line */
if (suc) /* of next line if not at EOF */
curwp->w_dotp = lforw(curwp->w_dotp);
/* and scan forward until we hit a <NL><NL> or <NL><TAB> /* and scan forword until we hit a <NL><NL> or <NL><TAB>
or a <NL><SPACE> */ or a <NL><SPACE> */
while (curwp->w_dotp != curbp->b_linep) { while (curwp->w_dotp != curbp->b_linep) {
if (llength(curwp->w_dotp) != 0 && if (llength(curwp->w_dotp) != 0 &&
#if PKCODE
((justflag == TRUE) || ((justflag == TRUE) ||
#endif
(lgetc(curwp->w_dotp, curwp->w_doto) != TAB && (lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
lgetc(curwp->w_dotp, curwp->w_doto) != ' ')) lgetc(curwp->w_dotp, curwp->w_doto) != ' '))
#if PKCODE
) )
#endif
curwp->w_dotp = lforw(curwp->w_dotp); curwp->w_dotp = lforw(curwp->w_dotp);
else else
break; break;
} }
/* and then backward until we are in a word */ /* and then backward until we are in a word */
while( backchar( FALSE, 1) && !inword()) ; suc = backchar(FALSE, 1);
while (suc && !inword()) {
suc = backchar(FALSE, 1);
}
curwp->w_doto = llength(curwp->w_dotp); /* and to the EOL */ curwp->w_doto = llength(curwp->w_dotp); /* and to the EOL */
} }
curwp->w_flag |= WFMOVE; /* force screen update */ curwp->w_flag |= WFMOVE; /* force screen update */
return TRUE; return TRUE;
} }
#endif
/* end of word.c */

35
word.h
View File

@ -1,24 +1,23 @@
/* word.h -- word processing functions */
#ifndef _WORD_H_ #ifndef _WORD_H_
#define _WORD_H_ #define _WORD_H_
#include "names.h" #define WORDPRO 1
/* Bindable functions */ int wrapword( int f, int n) ;
BINDABLE( wrapword) ; int backword( int f, int n) ;
BINDABLE( backword) ; int forwword( int f, int n) ;
BINDABLE( forwword) ; int upperword( int f, int n) ;
BINDABLE( upperword) ; int lowerword( int f, int n) ;
BINDABLE( lowerword) ; int capword( int f, int n) ;
BINDABLE( capword) ; int delfword( int f, int n) ;
BINDABLE( delfword) ; int delbword( int f, int n) ;
BINDABLE( delbword) ; #if WORDPRO
BINDABLE( gotobop) ; int gotobop( int f, int n) ;
BINDABLE( gotoeop) ; int gotoeop( int f, int n) ;
BINDABLE( fillpara) ; int fillpara( int f, int n) ;
BINDABLE( justpara) ; int justpara( int f, int n) ;
BINDABLE( killpara) ; int killpara( int f, int n) ;
BINDABLE( wordcount) ; int wordcount( int f, int n) ;
#endif
#endif #endif
/* end of word.h */

View File

@ -1,4 +1,5 @@
/* wrapper.c -- implements wrapper.h */ /* wrapper.c -- implements wrapper.h */
#include "wrapper.h" #include "wrapper.h"
#include <stdio.h> #include <stdio.h>
@ -6,6 +7,12 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#ifdef MINGW32
int mkstemp( char *template) {
return -1 ;
}
#endif
static void die( const char *err) { static void die( const char *err) {
fprintf( stderr, "fatal: %s\n", err) ; fprintf( stderr, "fatal: %s\n", err) ;
exit( EXIT_FAILURE) ; exit( EXIT_FAILURE) ;
@ -25,4 +32,12 @@ void xmkstemp( char *template) {
close( fd) ; close( fd) ;
} }
void *xmalloc( size_t size) {
void *ret = malloc( size) ;
if( !ret)
die( "Out of memory") ;
return ret ;
}
/* end of wrapper.c */ /* end of wrapper.c */

View File

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

117
wscreen.c Normal file
View File

@ -0,0 +1,117 @@
/* wscreen.c -- windows screen console for MINGW32 */
#include "wscreen.h"
#ifdef MINGW32
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
/* Standard error macro for reporting API errors */
#define PERR(bSuccess, api){if(!(bSuccess)) printf("%s:Error %d from %s \
on line %d\n", __FILE__, GetLastError(), api, __LINE__);}
static void cls( HANDLE hConsole )
{
COORD coordScreen = { 0, 0 }; /* here's where we'll home the
cursor */
BOOL bSuccess;
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
DWORD dwConSize; /* number of character cells in
the current buffer */
/* get the number of character cells in the current buffer */
bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
PERR( bSuccess, "GetConsoleScreenBufferInfo" );
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
/* fill the entire screen with blanks */
bSuccess = FillConsoleOutputCharacter( hConsole, (TCHAR) ' ',
dwConSize, coordScreen, &cCharsWritten );
PERR( bSuccess, "FillConsoleOutputCharacter" );
/* get the current text attribute */
bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
PERR( bSuccess, "ConsoleScreenBufferInfo" );
/* now set the buffer's attributes accordingly */
bSuccess = FillConsoleOutputAttribute( hConsole, csbi.wAttributes,
dwConSize, coordScreen, &cCharsWritten );
PERR( bSuccess, "FillConsoleOutputAttribute" );
/* put the cursor at (0, 0) */
bSuccess = SetConsoleCursorPosition( hConsole, coordScreen );
PERR( bSuccess, "SetConsoleCursorPosition" );
return;
}
void wcls( void) {
cls( GetStdHandle( STD_OUTPUT_HANDLE)) ;
}
static struct {
int width ;
int height ;
int curTop, curBot, curRight, curLeft ;
} Screen ;
void winit( void) {
CONSOLE_SCREEN_BUFFER_INFO csbInfo ;
wcls() ;
if( GetConsoleScreenBufferInfo(
GetStdHandle( STD_OUTPUT_HANDLE), &csbInfo)) {
Screen.width = csbInfo.dwSize.X ;
Screen.height = csbInfo.dwSize.Y ;
Screen.curLeft = csbInfo.srWindow.Left ;
Screen.curTop = csbInfo.srWindow.Top ;
Screen.curRight = csbInfo.srWindow.Right ;
Screen.curBot = csbInfo.srWindow.Bottom ;
}
}
int wwidth( void) {
return Screen.width ;
}
int wheight( void) {
return Screen.height ;
}
int wleft( void) {
return Screen.curLeft ;
}
int wtop( void) {
return Screen.curTop ;
}
int wright( void) {
return Screen.curRight ;
}
int wbottom( void) {
return Screen.curBot ;
}
void wgoxy( int x, int y) {
COORD coord ;
coord.X = x ;
coord.Y = y ;
SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE), coord );
}
void wtitle( const char *title) {
SetConsoleTitle( title) ;
}
#endif /* MINGW32 */
/* end of wscreen.c */

14
wscreen.h Normal file
View File

@ -0,0 +1,14 @@
/* wscreen.h -- character screen drawing */
void winit( void) ;
void wcls( void) ;
void wgoxy( int x, int y) ;
void wtitle( const char *title) ;
int wwidth( void) ;
int wheight( void) ;
int wleft( void) ;
int wright( void) ;
int wtop( void) ;
int wbottom( void) ;
/* end of wscreen.h */