This is util.c in view mode; [Download] [Up]
/*************************************************************************** * 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> #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 0; } int Interactive; /* 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 - 5, /* leave some extra space */ *kp = key_strokes, c; *buffer = '\0'; while ((c = *kp++) != '\0') { swritef(buffer, "%p ", c); buffer += strlen(buffer); if (buffer > buf_end) break; } } private int *slowp = 0; /* for waitchar() */ private SIGRESULT slowpoke(junk) int junk; { char buffer[100]; if (slowp) *slowp = YES; pp_key_strokes(buffer, sizeof (buffer)); f_mess(buffer); 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 /* MSDOS or MAC */ # 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 /* MSDOS or MAC */ 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 != 0 && *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 != 0 && *slow == YES) slowpoke(0); return c; #else /* MSDOS or MAC */ #ifdef MAC Keyonly = 1; if (charp() || in_macro()) { c = getch(); /* to avoid flicker */ if (slow != 0 && *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 */ } /* dir > 0 means forward; else means backward. */ char * StrIndex(dir, buf, charpos, what) int dir; 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 0; } int blnkp(buf) register char *buf; { register char c; while ((c = *buf++)!='\0' && (c == ' ' || c == '\t')) ; return c == 0; /* It's zero if we got to the end of the Line */ } int within_indent() { register char c; register int i; i = curchar; 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 != 0) 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 != 0) 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 == 0) 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; { int count = 0; register Line *prevp = nextp; line_diff = 0; if (nextp == endp) return char1 < char2; while (nextp || prevp) { if (nextp == endp || prevp == endp) break; if (nextp) nextp = nextp->l_next; if (prevp) prevp = prevp->l_prev; count += 1; } if (nextp == 0 && prevp == 0) return -1; line_diff = count; return 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 && !isword(c)) curchar += 1; if (eolp()) { if (curline->l_next == 0) return; SetLine(curline->l_next); to_word(dir); return; } } else { while (!bolp() && (c = linebuf[curchar - 1], !isword(c))) curchar -= 1; if (bolp()) { if (curline->l_prev == 0) return; SetLine(curline->l_prev); Eol(); to_word(dir); } } } /* Are there any modified buffers? Allp means include B_PROCESS buffers in the check. */ int ModBufs(allp) int allp; { register Buffer *b; for (b = world; b != 0; b = b->b_next) { if (b->b_type == B_SCRATCH) continue; if ((b->b_type == B_FILE || allp) && IsModified(b)) return 1; } return 0; } 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, "%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. */ int fixorder(line1, char1, line2, char2) register Line **line1, **line2; register int *char1, *char2; { Line *tline; int tchar; if (inorder(*line1, *char1, *line2, *char2)) return 0; tline = *line1; tchar = *char1; *line1 = *line2; *char1 = *char2; *line2 = tline; *char2 = tchar; return 1; } int inlist(first, what) register Line *first, *what; { while (first) { if (first == what) return 1; first = first->l_next; } return 0; } /* 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 == 0) return 0; val = emalloc((size_t) (strlen(str) + 1)); strcpy(val, str); return val; } #ifndef byte_copy void byte_copy(from, to, count) register char *from, *to; register size_t count; { while (count-- > 0) *to++ = *from++; } #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 != 0) && (*(lcontents(next)) == '\0') && (next->l_next != 0) && (*(lcontents(next->l_next)) == '\0')); } void linecopy(onto, atchar, from) register char *onto, *from; int atchar; { register char *endp = &onto[LBSIZE - 2]; onto += atchar; while ((*onto = *from++) != '\0') if (onto++ >= endp) len_error(ERROR); } 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]"); } void pipeclose(p) int *p; { (void) close(p[0]); (void) close(p[1]); } #endif /* UNIX */ /* NOSTRICT */ char * emalloc(size) size_t size; { register char *ptr; if ((ptr = malloc(size)) != NULL) return ptr; /* Try garbage collecting lines */ GCchunks(); if ((ptr = malloc(size)) != NULL) return ptr; /* Uh ... Oh screw it! */ error("[Out of memory] "); /* NOTREACHED */ } /* 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((char *) mainjmp, (char *) savejmp, sizeof (jmp_buf)); } void pop_env(savejmp) jmp_buf savejmp; { byte_copy((char *) savejmp, (char *) mainjmp, sizeof (jmp_buf)); } #ifdef LOAD_AV # if (defined(BSD4_2) && !defined(BSD2_10)) || defined(M_XENIX) # if defined(PURDUE_EE) && (defined(vax) || defined(gould)) void get_la(dp) double *dp; { *dp = (double) loadav(0) / 100.0; } # else /* !PURDUE_EE || (!vax && !gould) */ # if defined(NeXT) #include <sys/table.h> void get_la(dp) double *dp; { extern int table(); struct tbl_loadavg tl; if(table(TBL_LOADAVG, 0, &tl, 1, sizeof(tl)) < 0) *dp = 4.0; if(tl.tl_lscale == 0) *dp = 4.0; *dp = (double)tl.tl_avenrun[0] / tl.tl_lscale; } # else /* !NeXT */ #if defined(M_XENIX) # include <a.out.h> # define KERNEL "/xenix" # define FSCALE 256.0 #else # define KERNEL "/vmunix" # ifdef sun # include <sys/param.h> # endif # include <nlist.h> #endif static struct nlist nl[] = { { "_avenrun" }, #define X_AVENRUN 0 { "" } }; void get_la(dp) double *dp; { #if defined(sun) long avenrun[3]; #else #ifdef M_XENIX unsigned short avenrun[3]; #else double avenrun[3]; #endif #endif static int kmem = 0; extern long lseek proto((int, long, int)); if (kmem == -1) { *dp = 4.0; /* So shell commands will say "Chugging" */ return; } else if (kmem == 0) { if ((kmem = open("/dev/kmem", 0)) == -1) { f_mess("Can't open kmem for load average."); *dp = 4.0; return; } nlist(KERNEL, nl); } lseek(kmem, (long) nl[X_AVENRUN].n_value, 0); read(kmem, (char *) avenrun, sizeof(avenrun)); #if defined(sun) || defined(M_XENIX) *dp = (double) avenrun[0] / FSCALE; #else *dp = avenrun[0]; #endif } # endif /* !NeXT */ # endif /* !PURDUE... */ # else /* !BSD4_2 || BSD2_10 */ void get_la(dp) double *dp; { short avg[3]; gldav(avg); *dp = (double) avg[0] / 256; } # endif #endif /* LOAD_AV */ /* 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; extern char *ctime(); if (timep != 0) 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 || !s2) 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 || !s2) 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. Returns 1 if it returned because of keyboard input, or 0 otherwise. */ #ifdef MAC void SitFor(delay) int delay; { long start, end; #define Ticks ((long *) 0x16A) /* 1/60 sec */ Keyonly = 1; redisplay(); start = *Ticks; end = start + delay * 6; do if (InputPending = charp()) break; while (*Ticks < end); #undef Ticks } #else /* not MAC */ #ifndef MSDOS #if defined(BSD4_2) && !defined(BSD2_10) #include <sys/time.h> #endif #endif void SitFor(delay) int delay; { #ifndef MSDOS #if defined(BSD4_2) && !defined(BSD2_10) struct timeval timer; long readfds = 1; timer.tv_sec = (delay / 10); timer.tv_usec = (delay % 10) * 100000; if (charp()) return; /* gross that I had to snarf this from getch() */ if (!UpdMesg && !Asking) { /* Don't erase if we are asking */ if (mesgbuf[0] && !errormsg) message(NullStr); } redisplay(); select(1, &readfds, (long *)0, (long *)0, &timer); #else 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; if (charp()) return; nchars = (delay * cps[ospeed]) / 10; check_cnt = BufSize; redisplay(); while ((--nchars > 0) && !InputPending) { jputchar(0); if (--check_cnt == 0) { check_cnt = BufSize; InputPending = charp(); } } #endif #else /* MSDOS */ #include <bios.h> #include <dos.h> 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()) 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 */ int 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; } /* Just like strchr or index but doesn't match the string-ending null. */ char * jstrchr(sp, c) register char *sp; register int c; { while (*sp) { if (*sp == c) return sp; sp++; } return NULL; } void make_argv(argv, ap) register char *argv[]; va_list ap; { register char *cp; register int i = 0; argv[i++] = va_arg(ap, char *); argv[i++] = basename(argv[0]); while ((cp = va_arg(ap, char *)) != NULL) argv[i++] = cp; argv[i] = 0; } int pnt_line() { register Line *lp = curbuf->b_first; register int i; for (i = 0; lp != 0; i++, lp = lp->l_next) if (lp == curline) break; return i + 1; } char * ralloc(obj, size) register char *obj; size_t size; { register char *new; if (obj) new = realloc(obj, size); if (new == 0 || !obj) new = emalloc(size); return new; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.