home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari FTP
/
ATARI_FTP_0693.zip
/
ATARI_FTP_0693
/
Mint
/
Editors
/
mjovesrc.zoo
/
util.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-04
|
17KB
|
1,045 lines
/***************************************************************************
* This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
* is provided to you without charge, and with no warranty. You may give *
* away copies of JOVE, including sources, provided that this notice is *
* included in all the files. *
***************************************************************************/
#include "jove.h"
#include "ctype.h"
#include "termcap.h"
#include "disp.h"
#include "fp.h"
#include <signal.h>
#include <errno.h>
#define HAVE_STRERROR 1
#ifdef MAC
# include "mac.h"
#else
# ifdef STDARGS
# include <stdarg.h>
# else
# include <varargs.h>
# endif
#endif
#ifdef MSDOS
#include <time.h>
#endif
const struct cmd *
FindCmd(proc)
register void (*proc) proto((void));
{
register const struct cmd *cp;
for (cp = commands; cp->Name; cp++)
if (cp->c_proc == proc)
return cp;
return NULL;
}
bool Interactive = NO; /* True when we invoke with the command handler? */
data_obj *LastCmd;
char *ProcFmt = ": %f ";
void
ExecCmd(cp)
register data_obj *cp;
{
LastCmd = cp;
if (cp->Type & MAJOR_MODE) {
SetMajor((cp->Type >> 8));
} else if (cp->Type & MINOR_MODE) {
TogMinor((cp->Type >> 8));
} else switch (cp->Type&TYPEMASK) {
case MACRO:
do_macro((struct macro *) cp);
break;
case FUNCTION:
{
register struct cmd *cmd = (struct cmd *) cp;
if (cmd->c_proc) {
if ((cmd->Type & MODIFIER) &&
(BufMinorMode(curbuf, ReadOnly))) {
rbell();
message("[Buffer is read-only]");
} else
(*cmd->c_proc)();
}
}
}
}
Line *
lastline(lp)
register Line *lp;
{
register Line *next;
while ((next = lp->l_next) != NULL)
lp = next;
return lp;
}
char key_strokes[100],
*keys_p = key_strokes;
void
pp_key_strokes(buffer, size)
char *buffer;
size_t size;
{
char *buf_end = buffer + size - 1,
*kp = key_strokes,
c;
*buffer = '\0';
while ((c = *kp++) != '\0') {
swritef(buffer, (size_t) (buf_end-buffer), "%p ", c);
buffer += strlen(buffer);
if (buffer >= buf_end)
break;
}
}
private int *slowp = NULL; /* for waitchar() */
private SIGRESULT
slowpoke(junk)
int junk;
{
int save_errno = errno; /* Subtle, but necessary! */
char buffer[100];
if (slowp)
*slowp = YES;
pp_key_strokes(buffer, sizeof (buffer));
f_mess(buffer);
errno = save_errno;
SIGRETURN;
}
#ifdef UNIX
# ifdef BSD4_2
# define N_SEC 1 /* will be precisely 1 second on 4.2 */
# else
# define N_SEC 2 /* but from 1 to 2 seconds otherwise */
# endif
#else /* !UNIX */
# define N_SEC 1
int in_macro();
#endif /* !UNIX */
int
waitchar(slow)
int *slow;
{
int c;
#ifdef UNIX
unsigned int old_time;
SIGRESULT (*oldproc) proto((int));
#else /* !UNIX */
long sw, time();
#endif /* !UNIX */
slowp = slow;
if (in_macro()) /* make macros faster ... */
return getch();
/* If slow is a valid pointer and it's value is yes, then
we know we have already been slow during this sequence,
so we just wait for the character and then echo it. */
if (slow != NULL && *slow == YES) {
c = getch();
slowpoke(0);
return c;
}
#ifdef UNIX
oldproc = signal(SIGALRM, slowpoke);
if ((old_time = alarm((unsigned) N_SEC)) == 0)
old_time = UpdFreq;
c = getch();
(void) alarm(old_time);
(void) signal(SIGALRM, oldproc);
if (slow != NULL && *slow == YES)
slowpoke(0);
return c;
#else /* !UNIX */
#ifdef MAC
Keyonly = YES;
if (charp() || in_macro()) {
c = getch(); /* to avoid flicker */
if (slow != NULL && *slow == YES)
slowpoke();
return c;
}
#endif
time(&sw);
sw += N_SEC;
while (time(NULL) <= sw)
if (charp() || in_macro())
return getch();
#ifdef MAC
menus_off();
#endif
slowpoke();
c = getch();
slowpoke();
return c;
#endif /* !UNIX */
}
char *
StrIndex(dir, buf, charpos, what)
int dir; /* FORWARD or BACKWARD */
register char *buf;
int charpos;
register int what;
{
register char *cp = &buf[charpos];
register int c;
if (dir > 0) {
while ((c = *cp++) != '\0')
if ((c == what) != '\0')
return (cp - 1);
} else {
while (cp >= buf && (c = *cp--)!='\0')
if (c == what)
return (cp + 1);
}
return NULL;
}
bool
blnkp(buf)
register char *buf;
{
register char c;
do ; while ((c = *buf++)!='\0' && (c == ' ' || c == '\t'));
return c == 0; /* It's zero if we got to the end of the Line */
}
bool
within_indent()
{
register char c;
register int i;
i = curchar;
do ; while (--i >= 0 && ((c = linebuf[i]) == ' ' || c == '\t'));
return i < 0; /* it's < 0 if we got to the beginning */
}
Line *
next_line(line, num)
register Line *line;
register int num;
{
if (num < 0)
return prev_line(line, -num);
if (line)
while (--num >= 0 && line->l_next != NULL)
line = line->l_next;
return line;
}
Line *
prev_line(line, num)
register Line *line;
register int num;
{
if (num < 0)
return next_line(line, -num);
if (line)
while (--num >= 0 && line->l_prev != NULL)
line = line->l_prev;
return line;
}
void
DotTo(line, col)
Line *line;
int col;
{
Bufpos bp;
bp.p_line = line;
bp.p_char = col;
SetDot(&bp);
}
/* If bp->p_line is != current line, then save current line. Then set dot
to bp->p_line, and if they weren't equal get that line into linebuf. */
void
SetDot(bp)
register Bufpos *bp;
{
register int notequal;
if (bp == NULL)
return;
notequal = bp->p_line != curline;
if (notequal)
lsave();
if (bp->p_line)
curline = bp->p_line;
if (notequal)
getDOT();
curchar = bp->p_char;
if (curchar > length(curline))
curchar = length(curline);
}
void
ToLast()
{
SetLine(curbuf->b_last);
Eol();
}
int MarkThresh = 22; /* average screen size ... */
static int line_diff;
int
LineDist(nextp, endp)
register Line *nextp,
*endp;
{
(void) inorder(nextp, 0, endp, 0);
return line_diff;
}
int
inorder(nextp, char1, endp, char2)
register Line *nextp,
*endp;
int char1,
char2;
{
register Line *prevp = nextp;
line_diff = 0;
if (nextp == endp)
return char1 < char2;
while (nextp && prevp) {
nextp = nextp->l_next;
prevp = prevp->l_prev;
line_diff += 1;
if (nextp == endp)
return TRUE;
if (prevp == endp)
return FALSE;
}
while (nextp!=NULL && nextp!=endp) {
nextp = nextp->l_next;
line_diff += 1;
}
while (prevp!=NULL && prevp!=endp) {
prevp = prevp->l_prev;
line_diff += 1;
}
/* nextp == prevp implies both are NULL: the lines are not ordered */
return nextp==prevp? -1 : nextp==endp;
}
void
PushPntp(line)
register Line *line;
{
if (LineDist(curline, line) >= MarkThresh)
set_mark();
}
void
ToFirst()
{
SetLine(curbuf->b_first);
}
int
length(line)
Line *line;
{
return strlen(lcontents(line));
}
void
to_word(dir)
register int dir;
{
register char c;
if (dir == FORWARD) {
while ((c = linebuf[curchar]) != '\0' && !jisword(c))
curchar += 1;
if (eolp()) {
if (curline->l_next == NULL)
return;
SetLine(curline->l_next);
to_word(dir);
return;
}
} else {
while (!bolp() && (c = linebuf[curchar - 1], !jisword(c)))
curchar -= 1;
if (bolp()) {
if (curline->l_prev == NULL)
return;
SetLine(curline->l_prev);
Eol();
to_word(dir);
}
}
}
/* Are there any modified buffers? Allp means include B_PROCESS
buffers in the check. */
bool
ModBufs(allp)
bool allp;
{
register Buffer *b;
for (b = world; b != NULL; b = b->b_next)
if (b->b_type != B_SCRATCH
&& (b->b_type == B_FILE || allp)
&& IsModified(b))
return YES;
return NO;
}
char *
filename(b)
register Buffer *b;
{
return b->b_fname ? pr_name(b->b_fname, YES) : "[No file]";
}
char *
itoa(num)
register int num;
{
static char line[15];
swritef(line, sizeof(line), "%d", num);
return line;
}
int
min(a, b)
register int a,
b;
{
return (a < b) ? a : b;
}
int
max(a, b)
register int a,
b;
{
return (a > b) ? a : b;
}
void
tiewind(w, bp)
register Window *w;
register Buffer *bp;
{
int not_tied = (w->w_bufp != bp);
UpdModLine = YES; /* kludge ... but speeds things up considerably */
w->w_line = bp->b_dot;
w->w_char = bp->b_char;
w->w_bufp = bp;
if (not_tied)
CalcWind(w); /* ah, this has been missing since the
beginning of time! */
}
char *
lcontents(line)
register Line *line;
{
if (line == curline)
return linebuf;
else
return lbptr(line);
}
char *
ltobuf(line, buf)
Line *line;
char *buf;
{
if (line == curline) {
if (buf != linebuf)
strcpy(buf, linebuf);
Jr_Len = strlen(linebuf);
} else
getline(line->l_dline, buf);
return buf;
}
void
DOTsave(buf)
Bufpos *buf;
{
buf->p_line = curline;
buf->p_char = curchar;
}
/* Return none-zero if we had to rearrange the order. */
bool
fixorder(line1, char1, line2, char2)
register Line **line1,
**line2;
register int *char1,
*char2;
{
Line *tline;
int tchar;
if (inorder(*line1, *char1, *line2, *char2))
return NO;
tline = *line1;
tchar = *char1;
*line1 = *line2;
*char1 = *char2;
*line2 = tline;
*char2 = tchar;
return YES;
}
bool
inlist(first, what)
register Line *first,
*what;
{
while (first) {
if (first == what)
return YES;
first = first->l_next;
}
return NO;
}
/* Make `buf' (un)modified and tell the redisplay code to update the modeline
if it will need to be changed. */
int ModCount = 0;
void
modify()
{
if (!curbuf->b_modified) {
UpdModLine = YES;
curbuf->b_modified = YES;
}
DOLsave = YES;
if (!Asking)
ModCount += 1;
}
void
unmodify()
{
if (curbuf->b_modified) {
UpdModLine = YES;
curbuf->b_modified = NO;
}
}
int
numcomp(s1, s2)
register char *s1,
*s2;
{
register int count = 0;
while (*s1 != '\0' && *s1++ == *s2++)
count += 1;
return count;
}
char *
copystr(str)
char *str;
{
char *val;
if (str == NULL)
return NULL;
val = emalloc((size_t) (strlen(str) + 1));
strcpy(val, str);
return val;
}
#ifndef byte_copy
void
byte_copy(from, to, count)
UnivConstPtr *from;
UnivPtr *to;
register size_t count;
{
register const char *p = from;
register char *q = to;
if (count != 0) {
do *q++ = *p++; while (--count != 0);
}
}
#endif
void
len_error(flag)
int flag;
{
char *mesg = "[line too long]";
if (flag == COMPLAIN)
complain(mesg);
else
error(mesg);
}
/* Insert num number of c's at offset atchar in a linebuf of LBSIZE */
void
ins_c(c, buf, atchar, num, max)
int c;
char *buf;
int atchar,
num,
max;
{
register char *pp, *pp1;
register int len;
int numchars; /* number of characters to copy forward */
if (num <= 0)
return;
len = atchar + strlen(&buf[atchar]);
if (len + num >= max)
len_error(COMPLAIN);
pp = &buf[len + 1]; /* + 1 so we can --pp (not pp--) */
pp1 = &buf[len + num + 1];
numchars = len - atchar;
while (numchars-- >= 0)
*--pp1 = *--pp;
pp = &buf[atchar];
while (--num >= 0)
*pp++ = c;
}
int
TwoBlank()
{
register Line *next = curline->l_next;
return ((next != NULL) &&
(*(lcontents(next)) == '\0') &&
(next->l_next != NULL) &&
(*(lcontents(next->l_next)) == '\0'));
}
void
linecopy(onto, atchar, from)
register char *onto,
*from;
int atchar;
{
register char *endp = &onto[LBSIZE];
onto += atchar;
do {
if (onto >= endp)
len_error(ERROR);
} while ((*onto++ = *from++) != '\0');
}
char *
IOerr(err, file)
char *err, *file;
{
return sprint("Couldn't %s \"%s\".", err, file);
}
#ifdef UNIX
void
dopipe(p)
int *p;
{
if (pipe(p) == -1)
complain("[Pipe failed: %s]", strerror(errno));
}
void
pipeclose(p)
int *p;
{
(void) close(p[0]);
(void) close(p[1]);
}
#endif /* UNIX */
/* NOSTRICT */
UnivPtr
emalloc(size)
size_t size;
{
register UnivPtr ptr;
if ((ptr = malloc(size)) == NULL) {
/* Try garbage collecting lines */
GCchunks();
if ((ptr = malloc(size)) == NULL) {
/* Uh ... Oh screw it! */
error("[Out of memory] ");
/* NOTREACHED */
}
}
return ptr;
}
UnivPtr
erealloc(ptr, size)
UnivPtr ptr;
size_t size;
{
if ((ptr = realloc(ptr, size)) == NULL) {
/* no second chance for realloc! */
error("[out of memory]");
/* NOTREACHED */
}
return ptr;
}
/* Return the basename of file F. */
char *
basename(f)
register char *f;
{
register char *cp;
if ((cp = strrchr(f, '/')) != NULL)
return cp + 1;
else
#ifdef MSDOS
if (cp = strrchr(f, '\\'))
return cp + 1;
else
if (cp = strrchr(f, ':'))
return cp + 1;
#endif /* MSDOS */
return f;
}
void
push_env(savejmp)
jmp_buf savejmp;
{
byte_copy((UnivPtr) mainjmp, (UnivPtr) savejmp, sizeof (jmp_buf));
}
void
pop_env(savejmp)
jmp_buf savejmp;
{
byte_copy((UnivPtr) savejmp, (UnivPtr) mainjmp, sizeof (jmp_buf));
}
/* get the time buf, designated by *timep, from FROM to TO. */
char *
get_time(timep, buf, from, to)
time_t *timep;
char *buf;
int from,
to;
{
time_t now;
char *cp;
if (timep != NULL)
now = *timep;
else
(void) time(&now);
cp = ctime(&now) + from;
#ifndef MSDOS
if (to == -1)
#else /* MSDOS */
if ((to == -1) && (cp[strlen(cp)-1] == '\n'))
#endif /* MSDOS */
cp[strlen(cp) - 1] = '\0'; /* Get rid of \n */
else
cp[to - from] = '\0';
if (buf) {
strcpy(buf, cp);
return buf;
} else {
return cp;
}
}
int
casecmp(s1, s2)
register char *s1,
*s2;
{
if (s1==NULL || s2==NULL)
return 1; /* which is not zero ... */
while (CharUpcase(*s1) == CharUpcase(*s2++))
if (*s1++ == '\0')
return 0;
return (*s1 - *--s2);
}
int
casencmp(s1, s2, n)
register char *s1,
*s2;
register size_t n;
{
if (s1==NULL || s2==NULL)
return 1; /* which is not zero ... */
for (;;) {
if (n == 0)
return 0;
n--;
if (CharUpcase(*s1) != CharUpcase(*s2++))
return *s1 - *--s2;
if (*s1++ == '\0')
return 0;
}
}
void
null_ncpy(to, from, n)
char *to,
*from;
size_t n;
{
(void) strncpy(to, from, n);
to[n] = '\0';
}
/* Tries to pause for delay/10 seconds OR until a character is typed
at the keyboard. This works well on BSD4_2 and not so well on the
rest. */
#ifdef BSD4_2
# ifndef BSD2_10
# include <sys/time.h>
# endif
#endif
#ifdef MSDOS
# include <bios.h>
# include <dos.h>
#endif
void
SitFor(delay)
int delay;
{
#ifdef MAC
long start,
end;
#define Ticks ((long *) 0x16A) /* 1/60 sec */
Keyonly = YES;
redisplay();
start = *Ticks;
end = start + delay * 6;
do {
if ((InputPending = charp()) != NO)
break;
} while (*Ticks < end);
#undef Ticks
#else /* !MAC */
#ifndef MSDOS
if (!charp()) {
#if defined(BSD4_2) && !defined(BSD2_10)
struct timeval timer;
long readfds = 1;
/* So messages that aren't error messages don't
* hang around forever.
* Gross that I had to snarf this from getch()
*/
if (!UpdMesg && !Asking && mesgbuf[0] && !errormsg)
message(NullStr);
redisplay();
timer.tv_sec = (delay / 10);
timer.tv_usec = (delay % 10) * 100000;
select(1, &readfds, (long *)NULL, (long *)NULL, &timer);
#else /* !(defined(BSD4_2) && !defined(BSD2_10)) */
/* Pause by spitting NULs at the terminal. Ugh! */
static const int cps[] = {
0,
5,
7,
11,
13,
15,
20,
30,
60,
120,
180,
240,
480,
960,
1920,
1920,
};
register int nchars,
check_cnt;
nchars = (delay * cps[ospeed]) / 10;
check_cnt = BufSize;
redisplay();
if (!NP) {
while ((--nchars > 0) && !InputPending) {
jputchar(PC);
if (--check_cnt == 0) {
check_cnt = BufSize;
InputPending = charp();
}
}
}
#endif /* !(defined(BSD4_2) && !defined(BSD2_10)) */
}
#else /* MSDOS */
long start,
end;
#ifndef IBMPC
struct dostime_t tc;
#endif
redisplay();
#ifdef IBMPC
_bios_timeofday(_TIME_GETCLOCK, &start);
#else
_dos_gettime(&tc);
start = (long)(tc.hour*60L*60L*10L)+(long)(tc.minute*60L*10L)+
(long)(tc.second*10)+(long)(tc.hsecond/10);
#endif
end = (start + delay);
do {
if ((InputPending = charp()) != NO)
break;
#ifdef IBMPC
if (_bios_timeofday(_TIME_GETCLOCK, &start))
break; /* after midnight */
#else
start = (long)(tc.hour*60L*60L*10L)+(long)(tc.minute*60L*10L)+
(long)(tc.second*10)+(long)(tc.hsecond/10);
#endif
} while (start < end);
#endif /* MSDOS */
#endif /* !MAC */
}
bool
sindex(pattern, string)
register char *pattern,
*string;
{
register size_t len = strlen(pattern);
while (*string != '\0') {
if (*pattern == *string && strncmp(pattern, string, len) == 0)
return TRUE;
string += 1;
}
return FALSE;
}
void
make_argv(argv, ap)
register char *argv[];
va_list ap;
{
register int i = 0;
argv[i++] = va_arg(ap, char *);
argv[i++] = basename(argv[0]);
do ; while ((argv[i++] = va_arg(ap, char *)) != NULL);
}
int
pnt_line()
{
register Line *lp = curbuf->b_first;
register int i;
for (i = 0; lp != NULL; i++, lp = lp->l_next)
if (lp == curline)
break;
return i + 1;
}
/* Free, then allocate a block.
* Like erealloc, except that the previous contents of the block are lost.
*/
UnivPtr
freealloc(obj, size)
register UnivPtr obj;
size_t size;
{
register UnivPtr new = NULL;
if (obj)
new = realloc(obj, size);
if (new == NULL)
new = emalloc(size);
return new;
}
#ifndef HAVE_STRERROR
/*
* Unix version of strerror - map error number to descriptive string.
* ANSI systems should have this.
*/
char *
strerror(errnum)
int errnum;
{
extern int sys_nerr;
extern char *sys_errlist[];
if (errnum > 0 && errnum < sys_nerr)
return(sys_errlist[errnum]);
return sprint("Error number %d", errnum);
}
#endif