home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
vile-src.zip
/
vile-8.1
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-10-01
|
51KB
|
2,208 lines
/*
* This used to be MicroEMACS 3.9
* written by Dave G. Conroy.
* substantially modified by Daniel M. Lawrence
*
* Turned into "VI Like Emacs", a.k.a. vile, by Paul Fox
*
* (C)opyright 1987 by Daniel M. Lawrence
* MicroEMACS 3.9 can be copied and distributed freely for any
* non-commercial purposes. MicroEMACS 3.9 can only be incorporated
* into commercial software with the permission of the current author.
*
* The same goes for vile. -pgf, 1990-1995
*
*
* $Header: /usr/build/vile/vile/RCS/main.c,v 1.338 1998/10/01 09:17:03 tom Exp $
*
*/
/* Make global definitions not external */
#define realdef
#include "estruct.h" /* global structures and defines */
#include "edef.h" /* global definitions */
#include "nevars.h"
#include "nefunc.h"
#if OPT_LOCALE
#include <locale.h>
#include <ctype.h>
#endif
#if CC_NEWDOSCC
#include <io.h>
#if CC_DJGPP
#include <dpmi.h>
#include <go32.h>
#endif
#endif
#if SYS_VMS
#include <processes.h>
#endif
extern char *exec_pathname;
extern const char *const pathname[]; /* startup file path/name array */
/* for MSDOS, increase the default stack space */
#if SYS_MSDOS && CC_TURBO
unsigned _stklen = 32768U;
#endif
static void get_executable_dir (void);
static void global_val_init (void);
static void loop (void);
static void siginit (void);
static void start_debug_log(int ac, char **av);
static int cmd_mouse_motion(const CMDFUNC *cfp);
extern const int nametblsize;
/*--------------------------------------------------------------------------*/
#define GetArgVal(param) if (!*(++param))\
param = argv[++carg];\
if (param == 0)\
print_usage()
int
MainProgram(int argc, char *argv[])
{
int tt_opened;
register BUFFER *bp; /* temp buffer pointer */
register int carg; /* current arg to scan */
char *vileinit = NULL; /* the startup file or VILEINIT var */
int startstat = TRUE; /* result of running startup */
BUFFER *firstbp = NULL; /* ptr to first buffer in cmd line */
char *firstname = NULL; /* name of first buffer in cmd line */
int gotoflag = FALSE; /* do we need to goto line at start? */
int gline = FALSE; /* if so, what line? */
int helpflag = FALSE; /* do we need help at start? */
REGEXVAL *search_exp = 0; /* initial search-pattern */
const char *msg;
#ifdef VILE_OLE
int ole_register = FALSE;
#endif
#if DISP_X11 && !XTOOLKIT
int do_newgroup = FALSE; /* do we spawn at start? */
#endif
#if OPT_TAGS
int didtag = FALSE; /* look up a tag to start? */
char *tname = NULL;
#endif
#if OPT_ENCRYPT
char ekey[NPAT]; /* startup encryption key */
*ekey = EOS;
#endif
#if OPT_LOCALE
setlocale(LC_CTYPE, "");
#endif
#if OPT_NAMEBST
build_namebst(nametbl, 0, nametblsize - 1);
#endif
global_val_init(); /* global buffer values */
charinit(); /* character types -- we need these early */
winit(FALSE); /* command-line */
#if !SYS_UNIX
expand_wild_args(&argc, &argv);
#endif
prog_arg = argv[0]; /* this contains our only clue to exec-path */
start_debug_log(argc,argv);
get_executable_dir();
if (strcmp(pathleaf(prog_arg), "view") == 0)
set_global_b_val(MDREADONLY,TRUE);
#if DISP_X11
if (argc != 2 || strcmp(argv[1], "-V") != 0)
x_preparse_args(&argc, &argv);
#endif
/*
* Allow for I/O to the command-line before we initialize the screen
* driver.
*
* FIXME: we only know how to do this for displays that open the
* terminal in the same way for command-line and screen.
*/
siginit();
#if OPT_DUMBTERM
if (isatty(fileno(stdin))
&& isatty(fileno(stdout))) {
tt_opened = open_terminal(&dumb_term);
} else
#endif
tt_opened = open_terminal(&null_term);
/* Parse the command line */
for (carg = 1; carg < argc; ++carg) {
register char *param = argv[carg];
#if DISP_X11 && !XTOOLKIT
if (*param == '=') {
x_set_geometry(param);
continue;
}
#endif
/* Process Switches */
if (*param == '-') {
++param;
#if DISP_IBMPC || DISP_BORLAND
/* if it's a digit, it's probably a screen
resolution */
if (isDigit(*param)) {
current_res_name = param;
continue;
} else
#endif /* DISP_IBMPC */
switch (*param) {
#if DISP_X11 && !XTOOLKIT
case 'd':
if ((param = argv[++carg]) != 0)
x_set_dpy(param);
else
print_usage();
break;
case 'r':
x_set_rv();
break;
case 'f':
if (argv[++carg] != 0) {
if (strcmp(param, "foreground") == 0
|| strcmp(param, "fg") == 0)
x_setforeground(argv[carg]);
else if (!strcmp(param, "fork"))
do_newgroup = TRUE;
else
x_setfont(argv[carg]);
} else
print_usage();
break;
case 'b':
if (argv[++carg] != 0) {
if (strcmp(param, "background") == 0
|| strcmp(param, "bg") == 0)
x_setbackground(argv[carg]);
} else
print_usage();
break;
case 'n':
if (strcmp(param, "name") == 0
&& argv[++carg] != 0)
x_setname(argv[carg]);
else
print_usage();
break;
case 'w':
if (strcmp(param, "wm") == 0
&& argv[++carg] != 0)
x_set_wm_title(argv[carg]);
else
print_usage();
break;
#endif /* DISP_X11 */
case 'e': /* -e for Edit file */
case 'E':
set_global_b_val(MDVIEW,FALSE);
break;
case 'g': /* -g for initial goto */
case 'G':
gotoflag = TRUE;
GetArgVal(param);
gline = atoi(param);
break;
case 'h': /* -h for initial help */
case 'H':
helpflag = TRUE;
break;
#if OPT_ENCRYPT
case 'k': /* -k<key> for code key */
case 'K':
GetArgVal(param);
(void)strcpy(ekey, param);
(void)memset(param, '.', strlen(param));
ue_crypt((char *)0, 0);
ue_crypt(ekey, strlen(ekey));
break;
#endif
#ifdef VILE_OLE
case 'O':
if (param[1] == 'r')
ole_register = TRUE;
else
print_usage();
break;
#endif
case 's': /* -s for initial search string */
case 'S':
dosearch:
GetArgVal(param);
search_exp = new_regexval(param, global_b_val(MDMAGIC));
break;
#if OPT_TAGS
case 't': /* -t for initial tag lookup */
case 'T':
GetArgVal(param);
tname = param;
break;
#endif
case 'v': /* -v is view mode */
set_global_b_val(MDVIEW,TRUE);
break;
case 'R': /* -R is readonly mode (like "view") */
set_global_b_val(MDREADONLY,TRUE);
break;
case 'V':
#if DISP_NTWIN
gui_version(prog_arg);
#else
(void)printf("%s\n", getversion());
#endif
tidy_exit(GOODEXIT);
/* FALLTHROUGH */
case '?':
default: /* unknown switch */
print_usage();
}
} else if (*param == '+') { /* alternate form of -g */
if (*(++param) == '/') {
int len = strlen(param);
if (len > 0 && param[len-1] == '/')
param[--len] = EOS;
if (len == 0)
print_usage();
goto dosearch;
}
gotoflag = TRUE;
gline = atoi(param);
} else if (*param == '@') {
vileinit = ++param;
} else if (*param != EOS) {
/* Process an input file */
#if OPT_ENCRYPT
cryptkey = (*ekey != EOS) ? ekey : 0;
#endif
/* set up a buffer for this file */
bp = getfile2bp(param,FALSE,TRUE);
if (bp) {
bp->b_flag |= BFARGS; /* treat this as an argument */
make_current(bp); /* pull it to the front */
if (firstbp == 0) {
firstbp = bp;
firstname = param;
}
}
#if OPT_ENCRYPT
cryptkey = 0;
#endif
}
}
#ifdef VILE_OLE
if (ole_register)
{
/*
* Now that all command line options have been successfully
* parsed, register the OLE automation server and exit.
*/
ntwinio_oleauto_reg();
/* NOT REACHED */
}
#endif
/* if stdin isn't a terminal, assume the user is trying to pipe a
* file into a buffer.
*/
#if SYS_UNIX || SYS_VMS || SYS_MSDOS || SYS_WIN31 || SYS_OS2 || SYS_WINNT
#if DISP_NTWIN
if (stdin_data_available())
#else
if (!isatty(fileno(stdin)))
#endif
{
#if !DISP_X11
#if SYS_UNIX
# if HAS_TTYNAME
char *tty = ttyname(fileno(stderr));
# else
char *tty = "/dev/tty";
# endif
#else
FILE *in;
int fd;
#endif /* SYS_UNIX */
#endif /* DISP_X11 */
BUFFER *lastbp = firstbp;
int nline = 0;
bp = bfind(STDIN_BufName, BFARGS);
make_current(bp); /* pull it to the front */
if (firstbp == 0)
firstbp = bp;
ffp = fdopen(dup(fileno(stdin)), "r");
#if !DISP_X11
# if SYS_UNIX
/*
* Note: On Linux, the low-level close/dup operation
* doesn't work, since something hangs, apparently
* because substituting the file descriptor doesn't communicate
* properly up to the stdio routines.
*/
if ((freopen(tty, "r", stdin)) == 0
|| !isatty(fileno(stdin))) {
fputs("cannot open a terminal\n", stderr);
tidy_exit(BADEXIT);
}
#else
# if SYS_WINNT
# if DISP_NTCONS
/*
* The editor must reopen the console, not fd 0. If the console
* is not reopened, the nt console I/O routines die immediately
* when attempting to fetch a STDIN handle.
*/
freopen("con", "r", stdin);
# endif
# else
# if SYS_VMS
fd = open("tt:", O_RDONLY, S_IREAD); /* or sys$command */
# else /* e.g., DOS-based systems */
fd = fileno(stderr); /* this normally cannot be redirected */
# endif
if ((fd >= 0)
&& (close(0) >= 0)
&& (fd = dup(fd)) == 0
&& (in = fdopen(fd, "r")) != 0)
*stdin = *in;
# endif /* SYS_WINNT */
# endif /* SYS_UNIX */
#endif /* DISP_X11 */
(void)slowreadf(bp, &nline);
set_rdonly(bp, bp->b_fname, MDREADONLY);
(void)ffclose();
if (is_empty_buf(bp)) {
(void)zotbuf(bp);
curbp = firstbp = lastbp;
}
#if OPT_FINDERR
else {
set_febuff(bp->b_bname);
}
#endif
}
#endif
#if DISP_X11 && !XTOOLKIT
if (do_newgroup)
(void) newprocessgroup(TRUE,1);
#endif
/* initialize the editor */
if (!tt_opened)
siginit();
(void)open_terminal((TERM *)0);
TTkopen(); /* open the keyboard */
TTrev(FALSE);
if (vtinit() != TRUE) /* allocate display memory */
tidy_exit(BADEXIT);
winit(TRUE); /* windows */
/* this comes out to 70 on an 80 (or greater) column display */
{ register int fill;
fill = (7 * term.t_ncol) / 8; /* must be done after vtinit() */
if (fill > 70) fill = 70;
set_global_b_val(VAL_FILL, fill);
}
/* Create an unnamed buffer, so that the initialization-file will have
* something to work on. We don't pull in any of the command-line
* filenames yet, because some of the initialization stuff has to be
* triggered by switching buffers after reading the .vilerc file.
*
* If nothing modifies it, this buffer will be automatically removed
* when we switch to the first file (e.g., firstbp), because it is
* empty (and presumably isn't named the same as an actual file).
*/
bp = bfind(UNNAMED_BufName, 0);
bp->b_active = TRUE;
#if OPT_DOSFILES
/* an empty non-existent buffer defaults to line-style
favored by the OS */
make_local_b_val(bp, MDDOS);
set_b_val(bp, MDDOS, CRLF_LINES);
#endif
fix_cmode(bp, FALSE);
swbuffer(bp);
/* run the specified, or the system startup file here.
if vileinit is set, it's the name of the user's
command-line startup file, i.e. 'vile @mycmds'
*/
if (vileinit && *vileinit) {
if ((startstat = do_source(vileinit,1, FALSE)) != TRUE)
goto begin;
free(startup_file);
startup_file = strmalloc(vileinit);
} else {
/* now vileinit is the contents of their VILEINIT variable */
vileinit = getenv("VILEINIT");
if (vileinit != NULL) { /* set... */
int odiscmd;
BUFFER *vbp, *obp;
UINT oflags = 0;
if (*vileinit) { /* ...and not null */
/* mark as modified, to prevent
* undispbuff() from clobbering */
obp = curbp;
if (obp) {
oflags = obp->b_flag;
b_set_changed(obp);
}
if ((vbp=bfind(VILEINIT_BufName, BFEXEC)) == 0)
tidy_exit(BADEXIT);
/* don't want swbuffer to try to read it */
vbp->b_active = TRUE;
swbuffer(vbp);
b_set_scratch(vbp);
bprintf("%s", vileinit);
/* if we leave it scratch, swbuffer(obp)
may zot it, and we may zot it again */
b_clr_scratch(vbp);
set_rdonly(vbp, vbp->b_fname, MDVIEW);
/* go execute it! */
odiscmd = discmd;
discmd = FALSE;
startstat = dobuf(vbp);
discmd = odiscmd;
if (startstat != TRUE)
goto begin;
if (obp) {
swbuffer(obp);
obp->b_flag = oflags;
}
/* remove the now unneeded buffer */
b_set_scratch(vbp); /* make sure it will go */
(void)zotbuf(vbp);
}
} else { /* find and run .vilerc */
startstat = do_source(startup_file, 1, TRUE);
if (startstat != TRUE)
goto begin;
}
}
/* If there are any files to read, read the first one! Double-check,
* however, since a startup-script may have removed the first buffer.
*/
if (firstbp != 0
&& find_bp(firstbp)) {
if (find_bp(bp) && is_empty_buf(bp) && !b_is_changed(bp))
b_set_scratch(bp); /* remove the unnamed-buffer */
startstat = swbuffer(firstbp);
if (firstname)
set_last_file_edited(firstname);
if (bp2any_wp(bp) && bp2any_wp(firstbp))
zotwp(bp);
}
#if OPT_TAGS
else if (tname) {
cmdlinetag(tname);
didtag = TRUE;
}
#endif
msg = s_NULL;
if (helpflag) {
if (help(TRUE,1) != TRUE) {
msg =
"[Problem with help information. Type \":quit\" to exit if you wish]";
}
} else {
msg = "[Use ^A-h, ^X-h, or :help to get help]";
}
/* Deal with startup gotos and searches */
if (gotoflag + (search_exp != 0)
#if OPT_TAGS
+ (tname?1:0)
#endif
> 1) {
#if OPT_TAGS
msg = "[Search, goto and tag are used one at a time]";
#else
msg = "[Cannot search and goto at the same time]";
#endif
} else if (gotoflag) {
if (gotoline(gline != 0, gline) == FALSE) {
msg = "[Not that many lines in buffer]";
(void)gotoeob(FALSE,1);
}
} else if (search_exp) {
FreeIfNeeded(gregexp);
(void)strncpy0(pat, search_exp->pat, NPAT);
gregexp = search_exp->reg;
(void)forwhunt(FALSE, 0);
#if OPT_TAGS
} else if (tname && !didtag) {
cmdlinetag(tname);
#endif
}
#if OPT_POPUP_MSGS
purge_msgs();
#endif
if (startstat == TRUE) /* else there's probably an error message */
mlforce(msg);
begin:
(void)update(FALSE);
#if OPT_POPUP_MSGS
if (global_g_val(GMDPOPUP_MSGS) && (startstat != TRUE)) {
bp = bfind(MESSAGES_BufName, BFSCRTCH);
bsizes(bp);
TRACE(("Checking size of popup messages: %d\n", bp->b_linecount))
if (bp->b_linecount > 1) {
popup_msgs();
*mlsave = EOS;
}
}
if (global_g_val(GMDPOPUP_MSGS) == -TRUE)
set_global_g_val(GMDPOPUP_MSGS, FALSE);
#endif
/* We won't always be able to show messages before the screen is
* initialized. Give it one last chance.
*/
if ((startstat != TRUE) && *mlsave)
mlforce("%s", mlsave);
/* process commands */
loop();
/* NOTREACHED */
return BADEXIT;
}
/* this is nothing but the main command loop */
static void
loop(void)
{
const CMDFUNC
*cfp = NULL,
*last_cfp = NULL,
*last_failed_motion_cfp = NULL;
int s,c,f,n;
for_ever {
/* vi doesn't let the cursor rest on the newline itself. This
takes care of that. */
/* if we're inserting, or will be inserting again, then
suppress. this happens if we're using arrow keys
during insert */
if (is_at_end_of_line(DOT) && (DOT.o > w_left_margin(curwp)) &&
!insertmode && !cmd_mouse_motion(cfp))
backchar(TRUE,1);
/* same goes for end-of-file -- I'm actually not sure if
this can ever happen, but I _am_ sure that it's
a lot safer not to let it... */
if (is_header_line(DOT,curbp) && !is_empty_buf(curbp))
(void)backline(TRUE,1);
/* start recording for '.' command */
dotcmdbegin();
/* Fix up the screen */
s = update(FALSE);
/* get the next command from the keyboard */
c = kbd_seq();
/* if there is something on the command line, clear it */
if (kbd_length() > 0) {
mlerase();
if (s != SORTOFTRUE) /* did nothing due to typeahead */
(void)update(FALSE);
}
f = FALSE;
n = 1;
#if LATERMAYBE
/* insertion is too complicated to pop in
and out of so glibly... -pgf */
#ifdef insertmode
/* FIXME: Paul and Tom should check this over. */
if (insertmode != FALSE) {
if (!kbd_replaying(FALSE))
mayneedundo();
unkeystroke(c);
insert(f,n);
dotcmdfinish();
continue;
}
#endif /* insertmode */
#endif /* LATERMAYBE */
do_repeats(&c,&f,&n);
kregflag = 0;
/* flag the first time through for some commands -- e.g. subst
must know to not prompt for strings again, and pregion
must only restart the p-lines buffer once for each
command. */
calledbefore = FALSE;
/* and execute the command */
cfp = kcod2fnc(c);
if (cfp == &f_dotcmdplay &&
(last_cfp == &f_undo ||
last_cfp == &f_forwredo ||
last_cfp == &f_backundo ||
last_cfp == &f_inf_undo))
cfp = &f_inf_undo;
s = execute(cfp, f, n);
last_cfp = cfp;
/* stop recording for '.' command */
dotcmdfinish();
/* If this was a motion that failed, sound the alarm (like vi),
* but limit it to once, in case the user is holding down the
* autorepeat-key.
*/
if ( (cfp != NULL)
&& ((cfp->c_flags & MOTION) != 0)
&& (s == FALSE) ) {
if (cfp != last_failed_motion_cfp ||
global_g_val(GMDMULTIBEEP)) {
last_failed_motion_cfp = cfp;
kbd_alarm();
}
} else {
last_failed_motion_cfp = NULL; /* avoid noise! */
}
attrib_matches();
regionshape = EXACT;
}
}
/* attempt to locate the executable that contains our code.
* leave its directory name in exec_pathname and shorten prog_arg
* to the simple filename (no path).
*/
static void
get_executable_dir(void)
{
#if SYS_UNIX || SYS_VMS
char temp[NFILEN];
char *s, *t;
if (last_slash(prog_arg) == NULL) {
/* If there are no slashes, we can guess where we came from,
*/
if ((s = flook(prog_arg, FL_PATH|FL_EXECABLE)) != 0)
s = strmalloc(s);
} else {
/* if there _are_ slashes, then argv[0] was either
* absolute or relative. lengthen_path figures it out.
*/
s = strmalloc(lengthen_path(strcpy(temp, prog_arg)));
}
if (s == 0)
return;
t = pathleaf(s);
if (t != s) {
# if SYS_UNIX /* 't' points past slash */
t[-1] = EOS;
prog_arg = t;
# else /* 't' points to ']' */
*t = EOS;
prog_arg = t+1;
# endif
exec_pathname = s;
} else
free(s);
#endif
}
void
tidy_exit(int code)
{
ttclean (TRUE);
#if SYS_UNIX
setup_handler(SIGHUP,SIG_IGN);
#endif
ExitProgram(code);
}
#ifndef strmalloc
char *
strmalloc(const char *s)
{
register char *ns = castalloc(char,strlen(s)+1);
if (ns != 0)
(void)strcpy(ns,s);
return ns;
}
#endif
int
no_memory(const char *s)
{
mlforce("[%s] %s", out_of_mem, s);
return FALSE;
}
static void
global_val_init(void)
{
static const char expand_chars[] =
{ EXPC_THIS, EXPC_THAT, EXPC_SHELL, EXPC_TOKEN, EXPC_RPAT, 0 };
register int i;
char *s;
/* set up so the global value pointers point at the global
values. we never actually use the global pointers
directly, but when buffers get a copy of the
global_b_values structure, the pointers will still point
back at the global values, which is what we want */
for (i = 0; i <= NUM_G_VALUES; i++)
make_local_val(global_g_values.gv, i);
for (i = 0; i <= NUM_B_VALUES; i++)
make_local_val(global_b_values.bv, i);
for (i = 0; i <= NUM_W_VALUES; i++)
make_local_val(global_w_values.wv, i);
#if OPT_MAJORMODE
/*
* Built-in majormodes
*/
alloc_mode("c", TRUE);
#endif
/*
* Universal-mode defaults
*/
set_global_g_val(GMDABUFF, TRUE); /* auto-buffer */
set_global_g_val(GMDALTTABPOS, FALSE); /* emacs-style tab
positioning */
#ifdef GMDDIRC
set_global_g_val(GMDDIRC, FALSE); /* directory-completion */
#endif
set_global_g_val(GMDERRORBELLS, TRUE); /* alarms are noticeable */
#if OPT_FLASH
set_global_g_val(GMDFLASH, FALSE); /* beeps beep by default */
#endif
#ifdef GMDW32PIPES
set_global_g_val(GMDW32PIPES, is_winnt()); /* use native pipes? */
#endif
#if SYS_WINNT && defined(DISP_NTWIN)
/* Allocate console before spawning piped process? */
set_global_g_val(GMDFORCE_CONSOLE, is_win95());
#endif
#ifdef GMDHISTORY
set_global_g_val(GMDHISTORY, TRUE);
#endif
set_global_g_val(GMDMULTIBEEP, TRUE); /* multiple beeps for multiple
motion failures */
#if OPT_WORKING
set_global_g_val(GMDWORKING, TRUE); /* we put up "working..." */
#endif
/* which 8 bit chars are printable? */
set_global_g_val(GVAL_PRINT_LOW, 0);
set_global_g_val(GVAL_PRINT_HIGH, 0);
/* catnap times: */
/* how long to wait for ESC seq */
set_global_g_val(GVAL_TIMEOUTVAL, 500);
/* how long to wait for user seq */
#if SYS_MSDOS /* actually, 16-bit ints */
set_global_g_val(GVAL_TIMEOUTUSERVAL, 30000);
#else
set_global_g_val(GVAL_TIMEOUTUSERVAL, 60000);
#endif
#if SYS_WINNT
set_global_g_val(GVAL_SCROLLPAUSE, 0);
#endif
/* allow remapping by default */
set_global_g_val(GMDREMAP, TRUE);
set_global_g_val(GVAL_MAPLENGTH, 1200);
/* set noresolve-links by default in case we've got NFS problems */
#ifdef GMDRESOLVE_LINKS
set_global_g_val(GMDRESOLVE_LINKS, FALSE);
#endif
set_global_g_val_ptr(GVAL_EXPAND_CHARS, strmalloc(expand_chars));
set_global_g_val(GMDEXPAND_PATH,FALSE);
#ifdef GMDGLOB
set_global_g_val(GMDGLOB, TRUE);
#endif
#ifdef GVAL_GLOB
set_global_g_val_ptr(GVAL_GLOB, strmalloc("!echo %s"));
#endif
set_global_g_val(GMDIMPLYBUFF, FALSE); /* imply-buffer */
#if OPT_POPUPCHOICE
# if OPT_ENUM_MODES
set_global_g_val(GVAL_POPUP_CHOICES, POPUP_CHOICES_DELAYED);
# else
set_global_g_val(GMDPOPUP_CHOICES,TRUE);
# endif
#endif
#if OPT_FILEBACK
# if OPT_MSDOS_PATH
set_global_g_val_ptr(GVAL_BACKUPSTYLE, strmalloc(".bak"));
# else
set_global_g_val_ptr(GVAL_BACKUPSTYLE, strmalloc("off"));
# endif
#endif
#if OPT_POPUP_MSGS
set_global_g_val(GMDPOPUP_MSGS,-TRUE); /* popup-msgs */
#endif
#ifdef GMDRAMSIZE
set_global_g_val(GMDRAMSIZE, TRUE); /* show ram-usage */
#endif
set_global_g_val(GVAL_REPORT, 5); /* report changes */
#if OPT_XTERM
set_global_g_val(GMDXTERM_MOUSE,FALSE); /* mouse-clicking */
#endif
set_global_g_val(GMDWARNUNREAD,TRUE); /* warn if quitting without
looking at all buffers */
set_global_g_val(GMDWARNREREAD,TRUE); /* warn before rereading
a buffer */
set_global_g_val(GMDWARNRENAME,TRUE); /* warn before renaming
a buffer */
set_global_g_val(GMDSMOOTH_SCROLL, FALSE);
set_global_g_val(GMDSPACESENT, TRUE); /* add two spaces after each
sentence */
#if OPT_COLOR
set_global_g_val(GVAL_FCOLOR, C_WHITE); /* foreground color */
set_global_g_val(GVAL_BCOLOR, C_BLACK); /* background color */
#endif
/*
* Buffer-mode defaults
*/
set_global_b_val(MDAIND, FALSE); /* auto-indent */
set_global_b_val(MDASAVE, FALSE); /* auto-save */
set_global_b_val(MDBACKLIMIT, TRUE); /* limit backspacing to
insert point */
#ifdef MDCHK_MODTIME
set_global_b_val(MDCHK_MODTIME, FALSE); /* modtime-check */
#endif
#if !OPT_MAJORMODE
set_global_b_val(MDCMOD, FALSE); /* C mode */
#endif
#ifdef MDCRYPT
set_global_b_val(MDCRYPT, FALSE); /* crypt */
#endif
set_global_b_val(MDIGNCASE, FALSE); /* exact matches */
set_global_b_val(MDDOS, CRLF_LINES); /* on by default on DOS, off others */
set_global_b_val(MDMAGIC, TRUE); /* magic searches */
set_global_b_val( MDMETAINSBIND, TRUE); /* honor meta-bindings when
in insert mode */
set_global_b_val(MDNEWLINE, TRUE); /* trailing-newline */
set_global_b_val(MDREADONLY, FALSE); /* readonly */
set_global_b_val(MDSHOWMAT, FALSE); /* show-match */
set_global_b_val(MDSHOWMODE, TRUE); /* show-mode */
set_global_b_val(MDSWRAP, TRUE); /* scan wrap */
set_global_b_val(MDTABINSERT, TRUE); /* allow tab insertion */
set_global_b_val(MDTAGSRELTIV, FALSE); /* path relative tag lookups */
set_global_b_val(MDTERSE, FALSE); /* terse messaging */
#if OPT_HILITEMATCH
set_global_b_val(VAL_HILITEMATCH, 0); /* no hilite */
#endif
set_global_g_val(GVAL_MINI_HILITE, VAREV); /* reverse hilite */
#if OPT_UPBUFF
set_global_b_val(MDUPBUFF, TRUE); /* animated */
#endif
set_global_b_val(MDVIEW, FALSE); /* view-only */
set_global_b_val(MDWRAP, FALSE); /* wrap */
#if OPT_LCKFILES
/* locking defaults */
set_global_g_val(GMDUSEFILELOCK,FALSE); /* Use filelocks */
set_global_b_val(MDLOCKED, FALSE); /* LOCKED */
set_global_b_val_ptr(VAL_LOCKER, strmalloc("")); /* Name locker */
#endif
set_global_g_val(GMDRONLYVIEW, FALSE); /* Set view-on-readonly */
set_global_g_val(GMDRONLYRONLY, FALSE); /* Set readonly-on-readonly */
set_global_b_val(VAL_ASAVECNT, 256); /* autosave count */
#if OPT_MAJORMODE
set_submode_val("c", VAL_SWIDTH, 8); /* C file shiftwidth */
set_submode_val("c", VAL_TAB, 8); /* C file tab stop */
#else
set_global_b_val(VAL_C_SWIDTH, 8); /* C file shiftwidth */
set_global_b_val(VAL_C_TAB, 8); /* C file tab stop */
#endif
set_global_b_val(VAL_SWIDTH, 8); /* shiftwidth */
set_global_b_val(VAL_TAB, 8); /* tab stop */
set_global_b_val(VAL_TAGLEN, 0); /* significant tag length */
set_global_b_val(VAL_UNDOLIM, 10); /* undo limit */
set_global_b_val_ptr(VAL_TAGS, strmalloc("tags")); /* tags filename */
set_global_b_val_ptr(VAL_FENCES, strmalloc("{}()[]")); /* fences */
#if SYS_VMS
#define DEFAULT_CSUFFIX "\\.\\(\\([CHIS]\\)\\|CC\\|CXX\\|HXX\\)\\(;[0-9]*\\)\\?$"
#endif
#if SYS_MSDOS || SYS_WIN31
#define DEFAULT_CSUFFIX "\\.\\(\\([chis]\\)\\|cc\\|cpp\\|cxx\\|hxx\\)$"
#endif
#ifndef DEFAULT_CSUFFIX /* UNIX or OS2/HPFS (mixed-case names) */
#define DEFAULT_CSUFFIX "\\.\\(\\([Cchis]\\)\\|CC\\|cc\\|cpp\\|cxx\\|hxx\\|scm\\)$"
#endif
#if OPT_MAJORMODE
set_majormode_rexp("c", MVAL_SUFFIXES, DEFAULT_CSUFFIX);
#else
/* suffixes for C mode */
set_global_g_val_rexp(GVAL_CSUFFIXES,
new_regexval(
DEFAULT_CSUFFIX,
TRUE));
#endif
#define B_REGEXP(mode,value) \
set_global_b_val_rexp(mode, new_regexval(value, TRUE));
B_REGEXP( VAL_FENCE_BEGIN, "/\\*" );
B_REGEXP( VAL_FENCE_END, "\\*/" );
B_REGEXP( VAL_FENCE_IF, "^\\s*#\\s*if" );
B_REGEXP( VAL_FENCE_ELIF, "^\\s*#\\s*elif\\>" );
B_REGEXP( VAL_FENCE_ELSE, "^\\s*#\\s*else\\>" );
B_REGEXP( VAL_FENCE_FI, "^\\s*#\\s*endif\\>" );
/* where do paragraphs start? */
B_REGEXP( VAL_PARAGRAPHS, "^\\.[ILPQ]P\\>\\|^\\.P\\>\\|\
^\\.LI\\>\\|^\\.[plinb]p\\>\\|^\\.\\?\\s*$" );
/* where do comments start and end, for formatting them */
B_REGEXP( VAL_COMMENTS, "^\\s*/\\?\\(\\s*[#*>/]\\)\\+/\\?\\s*$" );
B_REGEXP( VAL_CMT_PREFIX, "^\\s*\\(\\(\\s*[#*>]\\)\\|\\(///*\\)\\)\\+" );
/* where do sections start? */
B_REGEXP( VAL_SECTIONS, "^[{\014]\\|^\\.[NS]H\\>\\|^\\.HU\\?\\>\\|\
^\\.[us]h\\>\\|^+c\\>" ); /* }vi */
/* where do sentences start? */
B_REGEXP( VAL_SENTENCES, "[.!?][])\"']* \\?$\\|[.!?][])\"']* \\|\
^\\.[ILPQ]P\\>\\|^\\.P\\>\\|^\\.LI\\>\\|^\\.[plinb]p\\>\\|^\\.\\?\\s*$" );
/*
* Window-mode defaults
*/
#ifdef WMDLINEWRAP
set_global_w_val(WMDLINEWRAP, FALSE); /* line-wrap */
#endif
set_global_w_val(WMDLIST, FALSE); /* list-mode */
set_global_w_val(WMDNUMBER, FALSE); /* number */
set_global_w_val(WMDHORSCROLL, TRUE); /* horizontal scrolling */
#ifdef WMDTERSELECT
set_global_w_val(WMDTERSELECT, TRUE); /* terse selections */
#endif
set_global_w_val(WVAL_SIDEWAYS, 0); /* list-mode */
if ((s = getenv("VILE_HELP_FILE")) == 0)
s = "vile.hlp";
helpfile = strmalloc(s);
if ((s = getenv("VILE_STARTUP_FILE")) == 0) {
#if SYS_MSDOS || SYS_WIN31 || SYS_OS2 || SYS_WINNT || SYS_VMS
s = "vile.rc";
#else /* SYS_UNIX */
s = ".vilerc";
#endif
}
startup_file = strmalloc(s);
if ((s = getenv("VILE_STARTUP_PATH")) == 0) {
#if SYS_MSDOS || SYS_WIN31 || SYS_OS2 || SYS_WINNT
s = "\\sys\\public\\;\\usr\\bin\\;\\bin\\;\\";
#else
#if SYS_VMS
s = "sys$login;sys$sysdevice:[vmstools];sys$library";
#else /* SYS_UNIX */
#if defined(VILE_STARTUP_PATH)
s = VILE_STARTUP_PATH;
#else
s = "/usr/local/lib/:/usr/local/:/usr/lib/";
#endif
#endif
#endif
}
startup_path = strmalloc(s);
#ifdef HELP_LOC
/*
* *NIX install will define this
*/
{
char temp[NFILEN];
int found = FALSE;
const char *t = startup_path;
while ((t = parse_pathlist(t, temp)) != 0) {
if (!strcmp(temp, HELP_LOC)) {
found = TRUE;
break;
}
}
if (!found) {
s = typeallocn(char, strlen(HELP_LOC) + 2 + strlen(startup_path));
lsprintf(s, "%s%c%s", HELP_LOC, PATHCHR, startup_path);
if (startup_path != NULL) /* memory leak! */
free(startup_path);
startup_path = s;
}
}
#endif
}
#if SYS_UNIX || SYS_MSDOS || SYS_WIN31 || SYS_OS2 || SYS_WINNT || SYS_VMS
/* ARGSUSED */
SIGT
catchintr (int ACTUAL_SIG_ARGS)
{
am_interrupted = TRUE;
#if SYS_MSDOS || SYS_OS2 || SYS_WINNT
sgarbf = TRUE; /* there's probably a ^C on the screen. */
#endif
setup_handler(SIGINT,catchintr);
if (im_waiting(-1))
longjmp(read_jmp_buf, signo);
SIGRET;
}
#endif
#ifndef interrupted /* i.e. unless it's a macro */
int
interrupted(void)
{
#if SYS_MSDOS && CC_DJGPP
if (_go32_was_ctrl_break_hit() != 0) {
while(keystroke_avail())
(void)keystroke();
return TRUE;
}
if (was_ctrl_c_hit() != 0) {
while(keystroke_avail())
(void)keystroke();
return TRUE;
}
if (am_interrupted)
return TRUE;
return FALSE;
#endif
}
#endif
void
not_interrupted(void)
{
am_interrupted = FALSE;
#if SYS_MSDOS
# if CC_DJGPP
(void)_go32_was_ctrl_break_hit(); /* flush any pending kbd ctrl-breaks */
(void)was_ctrl_c_hit(); /* flush any pending kbd ctrl-breaks */
# endif
#endif
}
#if SYS_MSDOS
# if CC_WATCOM
int dos_crit_handler(unsigned deverror, unsigned errcode, unsigned *devhdr)
# else
void dos_crit_handler(void)
# endif
{
# if CC_WATCOM
_hardresume((int)_HARDERR_FAIL);
return (int)_HARDERR_FAIL;
# else
# if ! CC_DJGPP
_hardresume(_HARDERR_FAIL);
# endif
# endif
}
#endif
static void
siginit(void)
{
#if SYS_UNIX
setup_handler(SIGINT,catchintr);
setup_handler(SIGHUP,imdying);
#ifdef SIGBUS
setup_handler(SIGBUS,imdying);
#endif
#ifdef SIGSYS
setup_handler(SIGSYS,imdying);
#endif
setup_handler(SIGSEGV,imdying);
setup_handler(SIGTERM,imdying);
/* #define DEBUG 1 */
#if DEBUG
setup_handler(SIGQUIT,imdying);
#else
setup_handler(SIGQUIT,SIG_IGN);
#endif
setup_handler(SIGPIPE,SIG_IGN);
#if defined(SIGWINCH) && ! DISP_X11
setup_handler(SIGWINCH,sizesignal);
#endif
#else
# if SYS_MSDOS
setup_handler(SIGINT,catchintr);
# if CC_DJGPP
_go32_want_ctrl_break(TRUE);
setcbrk(FALSE);
want_ctrl_c(TRUE);
hard_error_catch_setup();
# else
# if CC_WATCOM
{
/* clean up Warning from Watcom C */
void *ptrfunc = dos_crit_handler;
_harderr(ptrfunc);
}
# else /* CC_TURBO */
_harderr(dos_crit_handler);
# endif
# endif
# endif
# if SYS_OS2 || SYS_WINNT
setup_handler(SIGINT,catchintr);
#endif
#endif
}
static void
siguninit(void)
{
#if SYS_MSDOS
# if CC_DJGPP
_go32_want_ctrl_break(FALSE);
want_ctrl_c(FALSE);
hard_error_teardown();
setcbrk(TRUE);
# endif
#endif
}
/* do number processing if needed */
static void
do_num_proc(int *cp, int *fp, int *np)
{
register int c, f, n;
register int mflag;
register int oldn;
c = *cp;
if (isCntrl(c) || isspecial(c))
return;
f = *fp;
n = *np;
if (f)
oldn = n;
else
oldn = 1;
n = 1;
if ( isDigit(c) && c != '0' ) {
n = 0; /* start with a zero default */
f = TRUE; /* there is a # arg */
mflag = 1; /* current minus flag */
while ((isDigit(c) && !isspecial(c)) || (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 - */
mlwrite("arg:");
else
mlwrite("arg: %d",n * mflag);
c = kbd_seq(); /* get the next key */
}
n = n * mflag; /* figure in the sign */
}
*cp = c;
*fp = f;
*np = n * oldn;
}
/* do ^U-style repeat argument processing -- vile binds this to 'K' */
static void
do_rept_arg_proc(int *cp, int *fp, int *np)
{
register int c, f, n;
register int mflag;
register int oldn;
c = *cp;
if (c != reptc)
return;
f = *fp;
n = *np;
if (f)
oldn = n;
else
oldn = 1;
n = 4; /* start with a 4 */
f = TRUE; /* there is a # arg */
mflag = 0; /* that can be discarded. */
mlwrite("arg: %d",n);
while ( (isDigit( c=kbd_seq() ) && !isspecial(c))
|| c==reptc || c=='-'){
if (c == reptc) {
/* wow. what does this do? -pgf */
/* (i've been told it controls overflow...) */
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';
}
mlwrite("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;
}
*cp = c;
*fp = f;
*np = n * oldn;
}
/* handle all repeat counts */
void
do_repeats(int *cp, int *fp, int *np)
{
do_num_proc(cp,fp,np);
do_rept_arg_proc(cp,fp,np);
if (dotcmdmode == PLAY) {
if (dotcmdarg) /* then repeats are done by dotcmdcnt */
*np = 1;
} else {
/* then we want to cancel any dotcmdcnt repeats */
if (*fp) dotcmdarg = FALSE;
}
}
/* the vi ZZ command -- write all, then quit */
int
zzquit(int f, int n)
{
int thiscmd;
int cnt;
BUFFER *bp;
thiscmd = lastcmd;
cnt = any_changed_buf(&bp);
if (cnt) {
if (cnt > 1) {
mlprompt("Will write %d buffers. %s ", cnt,
clexec ? s_NULL : "Repeat command to continue.");
} else {
mlprompt("Will write buffer \"%s\". %s ",
bp->b_bname,
clexec ? s_NULL : "Repeat command to continue.");
}
if (!clexec && !isnamedcmd) {
if (thiscmd != kbd_seq())
return FALSE;
}
if (writeall(f,n,FALSE,TRUE,FALSE) != TRUE) {
return FALSE;
}
} else if (!clexec && !isnamedcmd) {
/* consume the next char. anyway */
if (thiscmd != kbd_seq())
return FALSE;
}
return quit(f, n);
}
/*
* Fancy quit command, as implemented by Norm. If the any buffer has
* changed do a write on that buffer and exit, otherwise simply exit.
*/
int
quickexit(int f, int n)
{
register int status;
if ((status = writeall(f,n,FALSE,TRUE,FALSE)) == TRUE)
status = quithard(f, n); /* conditionally quit */
return status;
}
/* Force quit by giving argument */
/* ARGSUSED */
int
quithard(int f GCC_UNUSED, int n GCC_UNUSED)
{
return quit(TRUE,1);
}
/*
* Quit command. If an argument, always quit. Otherwise confirm if a buffer
* has been changed and not written out.
*/
/* ARGSUSED */
int
quit(int f, int n GCC_UNUSED)
{
int cnt;
BUFFER *bp;
const char *sadj, *sverb;
#if OPT_PROCEDURES
{
static int exithooking;
if (!exithooking && *exithook) {
exithooking = TRUE;
run_procedure(exithook);
exithooking = FALSE;
}
}
#endif
if (f == FALSE) {
cnt = any_changed_buf(&bp);
sadj = "modified";
sverb = "Write";
if (cnt == 0 && global_g_val(GMDWARNUNREAD)) {
cnt = any_unread_buf(&bp);
sadj = "unread";
sverb = "Look at";
}
if (cnt != 0) {
if (cnt == 1)
mlforce(
"Buffer \"%s\" is %s. %s it, or use :q!",
bp->b_bname,sadj,sverb);
else
mlforce(
"There are %d %s buffers. %s them, or use :q!",
cnt,sadj,sverb);
return FALSE;
}
}
#if OPT_LCKFILES
/* Release all placed locks */
if ( global_g_val(GMDUSEFILELOCK) ) {
for_each_buffer(bp) {
if ( bp->b_active ) {
if (!b_val(curbp,MDLOCKED) &&
!b_val(curbp,MDVIEW))
release_lock(bp->b_fname);
}
}
}
#endif
siguninit();
#if OPT_WORKING
setup_handler(SIGALRM, SIG_IGN);
#endif
#if NO_LEAKS
{
beginDisplay(); /* ...this may take a while... */
/* free all of the global data structures */
onel_leaks();
path_leaks();
kbs_leaks();
bind_leaks();
map_leaks();
tags_leaks();
itb_leaks();
tb_leaks();
wp_leaks();
bp_leaks();
vt_leaks();
ev_leaks();
mode_leaks();
#if DISP_X11
x11_leaks();
#endif
free_local_vals(g_valnames, global_g_values.gv, global_g_values.gv);
free_local_vals(b_valnames, global_b_values.bv, global_b_values.bv);
free_local_vals(w_valnames, global_w_values.wv, global_w_values.wv);
FreeAndNull(gregexp);
FreeAndNull(patmatch);
#if OPT_MLFORMAT
FreeAndNull(modeline_format);
#endif
#if SYS_UNIX
if (strcmp(exec_pathname, "."))
FreeAndNull(exec_pathname);
#endif
/* whatever is left over must be a leak */
show_alloc();
}
#endif
tidy_exit(GOODEXIT);
/* NOTREACHED */
return FALSE;
}
/* ARGSUSED */
int
writequit(int f GCC_UNUSED, int n)
{
int s;
s = filesave(FALSE,n);
if (s != TRUE)
return s;
return quit(FALSE,n);
}
/*
* Abort.
* Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
* Sometimes called as a routine, to do general aborting of stuff.
*/
/* ARGSUSED */
int
esc_func(int f GCC_UNUSED, int n GCC_UNUSED)
{
dotcmdmode = STOP;
regionshape = EXACT;
doingopcmd = FALSE;
doingsweep = FALSE;
sweephack = FALSE;
opcmd = 0;
mlwarn("[Aborted]");
return ABORT;
}
/* tell the user that this command is illegal while we are in
VIEW (read-only) mode */
int
rdonly(void)
{
mlwarn("[No changes are allowed while in \"view\" mode]");
return FALSE;
}
/* ARGSUSED */
int
unimpl(int f GCC_UNUSED, int n GCC_UNUSED)
{
mlwarn("[Sorry, that vi command is unimplemented in vile ]");
return FALSE;
}
int
opercopy(int f, int n)
{
return unimpl(f,n);
}
int
opermove(int f, int n)
{
return unimpl(f,n);
}
int
opertransf(int f, int n)
{
return unimpl(f,n);
}
int
operglobals(int f, int n)
{
return unimpl(f,n);
}
int
opervglobals(int f, int n)
{
return unimpl(f,n);
}
int
source(int f, int n)
{
return unimpl(f,n);
}
int
visual(int f, int n)
{
return unimpl(f,n);
}
int
ex(int f, int n)
{
return unimpl(f,n);
}
/* ARGSUSED */
int
nullproc(int f GCC_UNUSED, int n GCC_UNUSED) /* user function that does (almost) NOTHING */
{
return TRUE;
}
/* ARGSUSED */
int
cntl_a_func(int f GCC_UNUSED, int n GCC_UNUSED) /* dummy function for binding to control-a prefix */
{
return TRUE;
}
/* ARGSUSED */
int
cntl_x_func(int f GCC_UNUSED, int n GCC_UNUSED) /* dummy function for binding to control-x prefix */
{
return TRUE;
}
/* ARGSUSED */
int
poundc_func(int f GCC_UNUSED, int n GCC_UNUSED) /* dummy function for binding to poundsign prefix */
{
return TRUE;
}
/* ARGSUSED */
int
unarg_func(int f GCC_UNUSED, int n GCC_UNUSED) /* dummy function for binding to universal-argument */
{
return TRUE;
}
/*----------------------------------------------------------------------------*/
#if OPT_SHOW_CTYPE
/* list the current chrs into the current buffer */
/* ARGSUSED */
static void
makectypelist(int dum1 GCC_UNUSED, void *ptr GCC_UNUSED)
{
static const struct {
ULONG mask;
const char *name;
} table[] = {
{ vl_upper, "Upr" },
{ vl_lower, "Lwr" },
{ vl_digit, "Num" },
{ vl_space, "Spc" },
{ vl_bspace, "DEL" },
{ vl_cntrl, "CTL" },
{ vl_print, "Prn" },
{ vl_punct, "Pun" },
{ vl_ident, "id" },
{ vl_pathn, "path" },
{ vl_wild, "*" },
{ vl_linespec, "arg" },
{ vl_fence, "()" },
{ vl_nonspace, "!S" },
{ vl_qident, "qid" },
#if OPT_WIDE_CTYPES
{ vl_scrtch, "tmp" },
{ vl_shpipe, "sh" },
#endif
{ 0, 0 }
};
register UINT i, j;
bprintf("--- Printable Characters %*P\n", term.t_ncol-1, '-');
for (i = 0; i < N_chars; i++) {
bprintf("\n%d\t", i);
if ((i == '\n') || (i == '\t')) /* vtlistc() may not do these */
bprintf("^%c", '@' | i);
#if OPT_LOCALE
else if (!isprint(i) && i > 127 && i < 160) /* C1 controls? */
bprintf(
global_w_val(WMDNONPRINTOCTAL)
? "\\%3o"
: "\\x%2x",
i);
#endif
else
bprintf("%c", i);
bputc('\t');
for (j = 0; table[j].name != 0; j++) {
if (j != 0)
bputc(' ');
bprintf("%*s",
strlen(table[j].name),
(vl_chartypes_[i] & table[j].mask)
? table[j].name
: "-");
}
}
}
int
desprint(int f GCC_UNUSED, int n GCC_UNUSED)
{
return liststuff(PRINTABLECHARS_BufName, FALSE, makectypelist, 0, (void *)0);
}
#endif /* OPT_SHOW_CTYPE */
/*----------------------------------------------------------------------------*/
/* initialize our version of the "chartypes" stuff normally in ctypes.h */
/* also called later, if charset-affecting modes change, for instance */
void
charinit(void)
{
register int c;
TRACE(("charinit lo=%d, hi=%d\n",
global_g_val(GVAL_PRINT_LOW),
global_g_val(GVAL_PRINT_HIGH)))
/* If we're using the locale functions, set our flags based on its
* tables. Note that just because you have 'setlocale()' doesn't mean
* that the tables are present or correct. But this is a start.
*/
#if OPT_LOCALE
for (c = 0; c < N_chars; c++) {
vl_chartypes_[c] = 0;
if (iscntrl(c)) vl_chartypes_[c] |= vl_cntrl;
if (isdigit(c)) vl_chartypes_[c] |= vl_digit;
if (islower(c)) vl_chartypes_[c] |= vl_lower;
if (isprint(c)) vl_chartypes_[c] |= vl_print;
if (ispunct(c)) vl_chartypes_[c] |= vl_punct;
if (isspace(c)) vl_chartypes_[c] |= vl_space;
if (isupper(c)) vl_chartypes_[c] |= vl_upper;
}
#else /* ! OPT_LOCALE */
(void)memset((char *)vl_chartypes_, 0, sizeof(vl_chartypes_));
/* control characters */
for (c = 0; c < ' '; c++)
vl_chartypes_[c] |= vl_cntrl;
vl_chartypes_[127] |= vl_cntrl;
/* lowercase */
for (c = 'a'; c <= 'z'; c++)
vl_chartypes_[c] |= vl_lower;
#if OPT_ISO_8859
for (c = 0xc0; c <= 0xd6; c++)
vl_chartypes_[c] |= vl_lower;
for (c = 0xd8; c <= 0xde; c++)
vl_chartypes_[c] |= vl_lower;
#endif
/* uppercase */
for (c = 'A'; c <= 'Z'; c++)
vl_chartypes_[c] |= vl_upper;
#if OPT_ISO_8859
for (c = 0xdf; c <= 0xf6; c++)
vl_chartypes_[c] |= vl_upper;
for (c = 0xf8; c <= 0xff; c++)
vl_chartypes_[c] |= vl_upper;
#endif
/* digits */
for (c = '0'; c <= '9'; c++)
vl_chartypes_[c] |= vl_digit;
/* punctuation */
for (c = '!'; c <= '/'; c++)
vl_chartypes_[c] |= vl_punct;
for (c = ':'; c <= '@'; c++)
vl_chartypes_[c] |= vl_punct;
for (c = '['; c <= '`'; c++)
vl_chartypes_[c] |= vl_punct;
for (c = LBRACE; c <= '~'; c++)
vl_chartypes_[c] |= vl_punct;
#if OPT_ISO_8859
for (c = 0xa1; c <= 0xbf; c++)
vl_chartypes_[c] |= vl_punct;
#endif
/* printable */
for (c = ' '; c <= '~'; c++)
vl_chartypes_[c] |= vl_print;
/* whitespace */
vl_chartypes_[' '] |= vl_space;
#if OPT_ISO_8859
vl_chartypes_[0xa0] |= vl_space;
#endif
vl_chartypes_['\t'] |= vl_space;
vl_chartypes_['\r'] |= vl_space;
vl_chartypes_['\n'] |= vl_space;
vl_chartypes_['\f'] |= vl_space;
#endif /* OPT_LOCALE */
/* legal in pathnames */
vl_chartypes_['.'] |= vl_pathn;
vl_chartypes_['_'] |= vl_pathn;
vl_chartypes_['~'] |= vl_pathn;
vl_chartypes_['-'] |= vl_pathn;
vl_chartypes_['*'] |= vl_pathn;
vl_chartypes_['/'] |= vl_pathn;
/* legal in "identifiers" */
vl_chartypes_['_'] |= vl_ident|vl_qident;
vl_chartypes_[':'] |= vl_qident;
#if SYS_VMS
vl_chartypes_['$'] |= vl_ident|vl_qident;
#endif
c = global_g_val(GVAL_PRINT_LOW);
if (c < HIGHBIT) c = HIGHBIT;
while ( c <= global_g_val(GVAL_PRINT_HIGH) && c < N_chars)
vl_chartypes_[c++] |= vl_print;
#if DISP_X11
for (c = 0; c < N_chars; c++) {
if (isPrint(c) && !gui_isprint(c)) {
vl_chartypes_[c] &= ~vl_print;
}
}
#endif
/* backspacers: ^H, rubout */
vl_chartypes_['\b'] |= vl_bspace;
vl_chartypes_[127] |= vl_bspace;
/* wildcard chars for most shells */
vl_chartypes_['*'] |= vl_wild;
vl_chartypes_['?'] |= vl_wild;
#if !OPT_VMS_PATH
#if SYS_UNIX
vl_chartypes_['~'] |= vl_wild;
#endif
vl_chartypes_[LBRACK] |= vl_wild;
vl_chartypes_[RBRACK] |= vl_wild;
vl_chartypes_[LBRACE] |= vl_wild;
vl_chartypes_[RBRACE] |= vl_wild;
vl_chartypes_['$'] |= vl_wild;
vl_chartypes_['`'] |= vl_wild;
#endif
/* ex mode line specifiers */
vl_chartypes_[','] |= vl_linespec;
vl_chartypes_['%'] |= vl_linespec;
vl_chartypes_['-'] |= vl_linespec;
vl_chartypes_['+'] |= vl_linespec;
vl_chartypes_[';'] |= vl_linespec;
vl_chartypes_['.'] |= vl_linespec;
vl_chartypes_['$'] |= vl_linespec;
vl_chartypes_['\''] |= vl_linespec;
/* fences */
vl_chartypes_[LBRACE] |= vl_fence;
vl_chartypes_[RBRACE] |= vl_fence;
vl_chartypes_[LPAREN] |= vl_fence;
vl_chartypes_[RPAREN] |= vl_fence;
vl_chartypes_[LBRACK] |= vl_fence;
vl_chartypes_[RBRACK] |= vl_fence;
#if OPT_VMS_PATH
vl_chartypes_[LBRACK] |= vl_pathn; /* actually, "<", ">" too */
vl_chartypes_[RBRACK] |= vl_pathn;
vl_chartypes_['$'] |= vl_pathn;
vl_chartypes_[':'] |= vl_pathn;
vl_chartypes_[';'] |= vl_pathn;
#endif
#if OPT_MSDOS_PATH
vl_chartypes_['\\'] |= vl_pathn;
vl_chartypes_[':'] |= vl_pathn;
#endif
#if OPT_WIDE_CTYPES
/* scratch-buffer-names (usually superset of vl_pathn) */
vl_chartypes_[(unsigned)SCRTCH_LEFT[0]] |= vl_scrtch;
vl_chartypes_[(unsigned)SCRTCH_RIGHT[0]] |= vl_scrtch;
vl_chartypes_[' '] |= vl_scrtch; /* ...to handle "[Buffer List]" */
#endif
for (c = 0; c < N_chars; c++) {
if (!(isSpace(c)))
vl_chartypes_[c] |= vl_nonspace;
if (isDigit(c))
vl_chartypes_[c] |= vl_linespec;
if (isAlpha(c) || isDigit(c))
vl_chartypes_[c] |= vl_ident|vl_pathn|vl_qident;
#if OPT_WIDE_CTYPES
if (isSpace(c) || isPrint(c))
vl_chartypes_[c] |= vl_shpipe;
if (ispath(c))
vl_chartypes_[c] |= vl_scrtch;
#endif
}
}
/***** Compiler specific Library functions ****/
#if OPT_RAMSIZE
/* These routines will allow me to track memory usage by placing
a layer on top of the standard system malloc() and free() calls.
with this code defined, the environment variable, $RAM, will
report on the number of bytes allocated via malloc.
with SHOWRAM defined, the number is also posted on the
end of the bottom mode line and is updated whenever it is changed.
*/
#undef realloc
#undef malloc
#undef free
typedef struct {
size_t length;
unsigned magic;
} RAMSIZE;
#define MAGIC_RAM 0x12345678
/* display the amount of RAM currently malloc'ed */
static void
display_ram_usage (void)
{
beginDisplay();
if (global_g_val(GMDRAMSIZE)) {
char mbuf[20];
int saverow = ttrow;
int savecol = ttcol;
if (saverow >= 0 && saverow < term.t_nrow
&& savecol >= 0 && savecol < term.t_ncol) {
(void)lsprintf(mbuf, "[%ld]", envram);
kbd_overlay(mbuf);
kbd_flush();
movecursor(saverow, savecol);
}
}
endofDisplay();
}
static char *old_ramsize(char *mp)
{
RAMSIZE *p = (RAMSIZE *)(mp - sizeof(RAMSIZE));
if (p->magic == MAGIC_RAM) {
mp = (char *)p;
envram -= p->length;
}
return mp;
}
static char *new_ramsize(char *mp, unsigned nbytes)
{
RAMSIZE *p = (RAMSIZE *)mp;
if (p != 0) {
p->length = nbytes;
p->magic = MAGIC_RAM;
envram += nbytes;
mp = (char *)((long)p + sizeof(RAMSIZE));
}
return mp;
}
/* reallocate mp with nbytes and track */
char *reallocate(char *mp, unsigned nbytes)
{
if (mp != 0) {
nbytes += sizeof(RAMSIZE);
mp = new_ramsize(realloc(old_ramsize(mp), nbytes), nbytes);
display_ram_usage();
} else
mp = allocate(nbytes);
return mp;
}
/* allocate nbytes and track */
char *allocate(
unsigned nbytes) /* # of bytes to allocate */
{
char *mp; /* ptr returned from malloc */
nbytes += sizeof(RAMSIZE);
if ((mp = malloc(nbytes)) != 0) {
(void)memset(mp, 0, nbytes); /* so we can use for calloc */
mp = new_ramsize(mp, nbytes);
display_ram_usage();
}
return mp;
}
/* release malloced memory and track */
void
release(char *mp) /* chunk of RAM to release */
{
if (mp) {
free(old_ramsize(mp));
display_ram_usage();
}
}
#endif /* OPT_RAMSIZE */
#if MALLOCDEBUG
mallocdbg(int f, int n)
{
int lvl;
lvl = malloc_debug(n);
mlwrite("malloc debug level was %d",lvl);
if (!f) {
malloc_debug(lvl);
} else if (n > 2) {
malloc_verify();
}
return TRUE;
}
#endif
/*
* the log file is left open, unbuffered. thus any code can do
*
* extern FILE *FF;
* fprintf(FF, "...", ...);
*
* to log events without disturbing the screen
*/
#ifdef DEBUGLOG
/* suppress the declaration so that the link will fail if someone uses it */
FILE *FF;
#endif
/*ARGSUSED*/
static void
start_debug_log(int ac GCC_UNUSED, char **av GCC_UNUSED)
{
#ifdef DEBUGLOG
int i;
FF = fopen("vilelog", "w");
setbuf(FF,NULL);
for (i = 0; i < ac; i++)
(void)fprintf(FF,"arg %d: %s\n",i,av[i]);
#endif
}
#if SYS_MSDOS
#if CC_TURBO
int
showmemory(int f, int n)
{
extern long coreleft(void);
mlforce("Memory left: %D bytes", coreleft());
return TRUE;
}
#endif
#if CC_WATCOM
int
showmemory(int f, int n)
{
mlforce("Watcom C doesn't provide a very useful 'memory-left' call.");
return TRUE;
}
#endif
#if CC_DJGPP
int
showmemory(int f, int n)
{
mlforce("Memory left: %D Kb virtual, %D Kb physical",
_go32_dpmi_remaining_virtual_memory()/1024,
_go32_dpmi_remaining_physical_memory()/1024);
return TRUE;
}
#endif
#endif /* SYS_MSDOS */
char *
strncpy0(char *t, const char *f, SIZE_T l)
{
(void)strncpy(t, f, l);
if (l)
t[l-1] = EOS;
return t;
}
#if defined(SA_RESTART)
/* several systems (SCO, SunOS) have sigaction without SA_RESTART */
/*
* Redefine signal in terms of sigaction for systems which have the
* SA_RESTART flag defined through <signal.h>
*
* This definition of signal will cause system calls to get restarted for a
* more BSD-ish behavior. This will allow us to use the OPT_WORKING feature
* for such systems.
*/
void
setup_handler(int sig, void (*disp) (int ACTUAL_SIG_ARGS))
{
struct sigaction act, oact;
act.sa_handler = disp;
sigemptyset(&act.sa_mask);
#ifdef SA_NODEFER /* don't rely on it. if it's not there, signals
probably aren't deferred anyway. */
act.sa_flags = SA_RESTART|SA_NODEFER ;
#else
act.sa_flags = SA_RESTART;
#endif
(void)sigaction(sig, &act, &oact);
}
#else
void
setup_handler(int sig, void (*disp) (int ACTUAL_SIG_ARGS))
{
(void)signal(sig, disp);
}
#endif
/* put us in a new process group, on command. we don't do this all the
* time since it interferes with suspending xvile on some systems with some
* shells. but we _want_ it other times, to better isolate us from signals,
* and isolate those around us (like buggy window/display managers) from
* _our_ signals. so we punt, and leave it up to the user.
*/
/* ARGSUSED */
int
newprocessgroup(int f GCC_UNUSED, int n GCC_UNUSED)
{
#if DISP_X11
int pid;
if (f) {
#ifndef SYS_VMS
pid = fork();
#else
pid = vfork(); /* VAX C and DEC C have a 'vfork()' */
#endif
if (pid > 0)
tidy_exit(GOODEXIT);
else if (pid < 0) {
fputs("cannot fork\n", stderr);
tidy_exit(BADEXIT);
}
}
# ifndef SYS_VMS
# ifdef HAVE_SETSID
(void)setsid();
# else
# ifdef HAVE_BSD_SETPGRP
(void) setpgrp(0, 0);
# else
(void)setpgrp();
# endif /* HAVE_BSD_SETPGRP */
# endif /* HAVE_SETSID */
# endif /* SYS_VMS */
#endif /* DISP_X11 */
return TRUE;
}
static int
cmd_mouse_motion(const CMDFUNC *cfp)
{
#if (OPT_XTERM || DISP_X11)
return cfp && CMD_U_FUNC(cfp) == mouse_motion;
#else
return FALSE;
#endif
}