Subject: MicroEMACS 3.6 (Part 4 of 8) Newsgroups: mod.sources Approved: jpn@panda.UUCP Mod.sources: Volume 4, Issue 101 Submitted by: ihnp4!itivax!duncan!lawrence echo x - bind.c sed 's/^X//' >bind.c <<'*-*-END-of-bind.c-*-*' X/* This file is for functions having to do with key bindings, X descriptions, help commands, and command line execution. X X written 11-feb-86 by Daniel Lawrence X */ X X#include X#include "estruct.h" X#include "edef.h" X#include "epath.h" X Xdeskey(f, n) /* describe the command for a certain key */ X{ X register int c; /* command character to describe */ X register char *ptr; /* string pointer to scan output strings */ X register KEYTAB *ktp; /* pointer into the command table */ X register int found; /* matched command flag */ X register NBIND *nptr; /* pointer into the name binding table */ X char outseq[80]; /* output buffer for command sequence */ X X /* prompt the user to type us a key to describe */ X mlwrite(": describe-key "); X X /* get the command sequence to describe */ X c = getckey(); /* get a command sequence */ X X /* change it to something we can print as well */ X cmdstr(c, &outseq[0]); X X /* and dump it out */ X ptr = &outseq[0]; X while (*ptr) X (*term.t_putchar)(*ptr++); X (*term.t_putchar)(' '); /* space it out */ X X /* find the right ->function */ X ktp = &keytab[0]; X found = FALSE; X while (ktp->k_fp != NULL) { X if (ktp->k_code == c) { X found = TRUE; X break; X } X ++ktp; X } X X if (!found) X strcpy(outseq,"Not Bound"); X else { X /* match it against the name binding table */ X nptr = &names[0]; X strcpy(outseq,"[Bad binding]"); X while (nptr->n_func != NULL) { X if (nptr->n_func == ktp->k_fp) { X strcpy(outseq, nptr->n_name); X break; X } X ++nptr; X } X } X X /* output the command sequence */ X ptr = &outseq[0]; X while (*ptr) X (*term.t_putchar)(*ptr++); X} X Xcmdstr(c, seq) /* change a key command to a string we can print out */ X Xint c; /* sequence to translate */ Xchar *seq; /* destination string for sequence */ X X{ X char *ptr; /* pointer into current position in sequence */ X X ptr = seq; X X /* apply meta sequence if needed */ X if (c & META) { X *ptr++ = 'M'; X *ptr++ = '-'; X } X X /* apply ^X sequence if needed */ X if (c & CTLX) { X *ptr++ = '^'; X *ptr++ = 'X'; X } X X /* apply SPEC sequence if needed */ X if (c & SPEC) { X *ptr++ = 'F'; X *ptr++ = 'N'; X } X X /* apply control sequence if needed */ X if (c & CTRL) { X *ptr++ = '^'; X } X X c = c & 255; /* strip the prefixes */ X X /* and output the final sequence */ X X *ptr++ = c; X *ptr = 0; /* terminate the string */ X} X Xhelp(f, n) /* give me some help!!!! X bring up a fake buffer and read the help file X into it with view mode */ X{ X register int status; /* status of I/O operations */ X register WINDOW *wp; /* scnaning pointer to windows */ X register int i; /* index into help file names */ X char fname[NSTRING]; /* buffer to construct file name in */ X X /* search through the list of help files */ X for (i=2; i < NPNAMES; i++) { X strcpy(fname, pathname[i]); X strcat(fname, pathname[1]); X status = ffropen(fname); X if (status == FIOSUC) X break; X } X X if (status == FIOFNF) { X mlwrite("[Help file is not online]"); X return(FALSE); X } X ffclose(); /* close the file to prepare for to read it in */ X X /* split the current window to make room for the help stuff */ X if (splitwind(FALSE, 1) == FALSE) X return(FALSE); X X /* and read the stuff in */ X if (getfile(fname, FALSE) == FALSE) X return(FALSE); X X /* make this window in VIEW mode, update all mode lines */ X curwp->w_bufp->b_mode |= MDVIEW; X wp = wheadp; X while (wp != NULL) { X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X return(TRUE); X} X Xint (*fncmatch(fname))() /* match fname to a function in the names table X and return any match or NULL if none */ X Xchar *fname; /* name to attempt to match */ X X{ X register NBIND *ffp; /* pointer to entry in name binding table */ X X /* scan through the table, returning any match */ X ffp = &names[0]; X while (ffp->n_func != NULL) { X if (strcmp(fname, ffp->n_name) == 0) X return(ffp->n_func); X ++ffp; X } X return(NULL); X} X X/* bindtokey: add a new key to the key binding table X*/ X Xbindtokey(f, n) X Xint f, n; /* command arguments [IGNORED] */ X X{ X register int c; /* command key to bind */ X register (*kfunc)(); /* ptr to the requexted function to bind to */ X register char *ptr; /* ptr to dump out input key string */ X register KEYTAB *ktp; /* pointer into the command table */ X register int found; /* matched command flag */ X char outseq[80]; /* output buffer for keystroke sequence */ X int (*getname())(); X X /* prompt the user to type in a key to bind */ X mlwrite(": bind-to-key "); X X /* get the function name to bind it to */ X kfunc = getname(); X if (kfunc == NULL) { X mlwrite("[No such function]"); X return(FALSE); X } X (*term.t_putchar)(' '); /* space it out */ X (*term.t_flush)(); X X /* get the command sequence to bind */ X c = getckey(); /* get a command sequence */ X X /* change it to something we can print as well */ X cmdstr(c, &outseq[0]); X X /* and dump it out */ X ptr = &outseq[0]; X while (*ptr) X (*term.t_putchar)(*ptr++); X X /* search the table to see if it exists */ X ktp = &keytab[0]; X found = FALSE; X while (ktp->k_fp != NULL) { X if (ktp->k_code == c) { X found = TRUE; X break; X } X ++ktp; X } X X if (found) { /* it exists, just change it then */ X ktp->k_fp = kfunc; X } else { /* otherwise we need to add it to the end */ X /* if we run out of binding room, bitch */ X if (ktp >= &keytab[NBINDS]) { X mlwrite("Binding table FULL!"); X return(FALSE); X } X X ktp->k_code = c; /* add keycode */ X ktp->k_fp = kfunc; /* and the function pointer */ X ++ktp; /* and make sure the next is null */ X ktp->k_code = 0; X ktp->k_fp = NULL; X } X X return(TRUE); X} X X/* unbindkey: delete a key from the key binding table X*/ X Xunbindkey(f, n) X Xint f, n; /* command arguments [IGNORED] */ X X{ X register int c; /* command key to unbind */ X register char *ptr; /* ptr to dump out input key string */ X register KEYTAB *ktp; /* pointer into the command table */ X register KEYTAB *sktp; /* saved pointer into the command table */ X register int found; /* matched command flag */ X char outseq[80]; /* output buffer for keystroke sequence */ X X /* prompt the user to type in a key to unbind */ X mlwrite(": unbind-key "); X X /* get the command sequence to unbind */ X c = getckey(); /* get a command sequence */ X X /* change it to something we can print as well */ X cmdstr(c, &outseq[0]); X X /* and dump it out */ X ptr = &outseq[0]; X while (*ptr) X (*term.t_putchar)(*ptr++); X X /* search the table to see if the key exists */ X ktp = &keytab[0]; X found = FALSE; X while (ktp->k_fp != NULL) { X if (ktp->k_code == c) { X found = TRUE; X break; X } X ++ktp; X } X X /* if it isn't bound, bitch */ X if (!found) { X mlwrite("[Key not bound]"); X return(FALSE); X } X X /* save the pointer and scan to the end of the table */ X sktp = ktp; X while (ktp->k_fp != NULL) X ++ktp; X --ktp; /* backup to the last legit entry */ X X /* copy the last entry to the current one */ X sktp->k_code = ktp->k_code; X sktp->k_fp = ktp->k_fp; X X /* null out the last one */ X ktp->k_code = 0; X ktp->k_fp = NULL; X return(TRUE); X} X X/* namedcmd: execute a named command even if it is not bound X*/ X Xnamedcmd(f, n) X Xint f, n; /* command arguments [passed through to command executed] */ X X{ X register (*kfunc)(); /* ptr to the requexted function to bind to */ X int (*getname())(); X X /* prompt the user to type a named command */ X mlwrite(": "); X X /* and now get the function name to execute */ X kfunc = getname(); X if (kfunc == NULL) { X mlwrite("[No such function]"); X return(FALSE); X } X X /* and then execute the command */ X return((*kfunc)(f, n)); X} X Xdesbind(f, n) /* describe bindings X bring up a fake buffer and list the key bindings X into it with view mode */ X{ X register WINDOW *wp; /* scnaning pointer to windows */ X register KEYTAB *ktp; /* pointer into the command table */ X register NBIND *nptr; /* pointer into the name binding table */ X register BUFFER *bp; /* buffer to put binding list into */ X char *strp; /* pointer int string to send */ X int cpos; /* current position to use in outseq */ X char outseq[80]; /* output buffer for keystroke sequence */ X X /* split the current window to make room for the binding list */ X if (splitwind(FALSE, 1) == FALSE) X return(FALSE); X X /* and get a buffer for it */ X bp = bfind("Binding list", TRUE, 0); X if (bp == NULL || bclear(bp) == FALSE) { X mlwrite("Can not display binding list"); X return(FALSE); X } X X /* let us know this is in progress */ X mlwrite("[Building buffer list]"); X X /* disconect the current buffer */ X if (--curbp->b_nwnd == 0) { /* Last use. */ X curbp->b_dotp = curwp->w_dotp; X curbp->b_doto = curwp->w_doto; X curbp->b_markp = curwp->w_markp; X curbp->b_marko = curwp->w_marko; X } X X /* connect the current window to this buffer */ X curbp = bp; /* make this buffer current in current window */ X bp->b_mode = 0; /* no modes active in binding list */ X bp->b_nwnd++; /* mark us as more in use */ X wp = curwp; X wp->w_bufp = bp; X wp->w_linep = bp->b_linep; X wp->w_flag = WFHARD|WFFORCE|WFHARD; X wp->w_dotp = bp->b_dotp; X wp->w_doto = bp->b_doto; X wp->w_markp = NULL; X wp->w_marko = 0; X X /* build the contents of this window, inserting it line by line */ X nptr = &names[0]; X while (nptr->n_func != NULL) { X X /* add in the command name */ X strcpy(outseq, nptr->n_name); X cpos = strlen(outseq); X X /* search down any keys bound to this */ X ktp = &keytab[0]; X while (ktp->k_fp != NULL) { X if (ktp->k_fp == nptr->n_func) { X /* padd out some spaces */ X while (cpos < 25) X outseq[cpos++] = ' '; X X /* add in the command sequence */ X cmdstr(ktp->k_code, &outseq[cpos]); X while (outseq[cpos] != 0) X ++cpos; X X /* and add it as a line into the buffer */ X strp = &outseq[0]; X while (*strp != 0) X linsert(1, *strp++); X lnewline(); X X cpos = 0; /* and clear the line */ X } X ++ktp; X } X X /* if no key was bound, we need to dump it anyway */ X if (cpos > 0) { X outseq[cpos] = 0; X strp = &outseq[0]; X while (*strp != 0) X linsert(1, *strp++); X lnewline(); X } X X /* and on to the next name */ X ++nptr; X } X X curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */ X curbp->b_flag &= ~BFCHG; /* don't flag this as a change */ X wp->w_dotp = lforw(bp->b_linep);/* back to the begining */ X wp->w_doto = 0; X wp = wheadp; /* and update ALL mode lines */ X while (wp != NULL) { X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X mlwrite(""); /* clear the mode line */ X return(TRUE); X} X X/* execcmd: Execute a command line command to be typed in X by the user */ X Xexeccmd(f, n) X Xint f, n; /* default Flag and Numeric argument */ X X{ X register int status; /* status return */ X char cmdstr[NSTRING]; /* string holding command to execute */ X X /* get the line wanted */ X if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE) X return(status); X X return(docmd(cmdstr)); X} X X/* docmd: take a passed string as a command line and translate X it to be executed as a command. This function will be X used by execute-command-line and by all source and X startup files. X X format of the command line is: X X {# arg} {} X*/ X Xdocmd(cline) X Xchar *cline; /* command line to execute */ X X{ X register char *cp; /* pointer to current position in command */ X register char *tp; /* pointer to current position in token */ X register int f; /* default argument flag */ X register int n; /* numeric repeat value */ X register int sign; /* sign of numeric argument */ X register int (*fnc)(); /* function to execute */ X register int status; /* return status of function */ X register int oldcle; /* old contents of clexec flag */ X char token[NSTRING]; /* next token off of command line */ X int (*fncmatch())(); X char *gettok(); X X /* first set up the default command values */ X f = FALSE; X n = 1; X X cp = cline; /* start at the begining of the line */ X cp = gettok(cp, token); /* and grab the first token */ X X /* check for and process numeric leadin argument */ X if ((token[0] >= '0' && token[0] <= '9') || token[0] == '-') { X f = TRUE; X n = 0; X tp = &token[0]; X X /* check for a sign! */ X sign = 1; X if (*tp == '-') { X ++tp; X sign = -1; X } X X /* calc up the digits in the token string */ X while(*tp) { X if (*tp >= '0' && *tp <= '9') X n = n * 10 + *tp - '0'; X ++tp; X } X n *= sign; /* adjust for the sign */ X X /* and now get the command to execute */ X cp = gettok(cp, token); /* grab the next token */ X } X X /* and match the token to see if it exists */ X if ((fnc = fncmatch(token)) == NULL) { X mlwrite("[No such Function]"); X return(FALSE); X } X X /* save the arguments and go execute the command */ X strcpy(sarg, cp); /* save the rest */ X oldcle = clexec; /* save old clexec flag */ X clexec = TRUE; /* in cline execution */ X status = (*fnc)(f, n); /* call the function */ X clexec = oldcle; /* restore clexec flag */ X return(status); X} X X/* gettok: chop a token off a string X return a pointer past the token X*/ X Xchar *gettok(src, tok) X Xchar *src, *tok; /* source string, destination token */ X X{ X /* first scan past any whitespace in the source string */ X while (*src == ' ' || *src == '\t') X ++src; X X /* if quoted, go till next quote */ X if (*src == '"') { X ++src; /* past the quote */ X while (*src != 0 && *src != '"') X *tok++ = *src++; X ++src; /* past the last quote */ X *tok = 0; /* terminate token and return */ X return(src); X } X X /* copy until we find the end or whitespace */ X while (*src != 0 && *src != ' ' && *src != '\t') X *tok++ = *src++; X X /* terminate tok and return */ X *tok = 0; X return(src); X} X X/* nxtarg: grab the next token out of sarg, return it, and X chop it of sarg */ X Xnxtarg(tok) X Xchar *tok; /* buffer to put token into */ X X{ X char *newsarg; /* pointer to new begining of sarg */ X char *gettok(); X X newsarg = gettok(sarg, tok); /* grab the token */ X strcpy(sarg, newsarg); /* and chop it of sarg */ X return(TRUE); X} X Xgetckey() /* get a command key sequence from the keyboard */ X X{ X register int c; /* character fetched */ X register char *tp; /* pointer into the token */ X char tok[NSTRING]; /* command incoming */ X X /* check to see if we are executing a command line */ X if (clexec) { X nxtarg(tok); /* get the next token */ X X /* parse it up */ X tp = &tok[0]; X c = 0; X X /* first, the META prefix */ X if (*tp == 'M' && *(tp+1) == '-') { X c = META; X tp += 2; X } X X /* next the function prefix */ X if (*tp == 'F' && *(tp+1) == 'N') { X c |= SPEC; X tp += 2; X } X X /* control-x as well... */ X if (*tp == '^' && *(tp+1) == 'X') { X c |= CTLX; X tp += 2; X } X X /* a control char? */ X if (*tp == '^' & *(tp+1) != 0) { X c |= CTRL; X ++tp; X } X X /* make sure we are not lower case */ X if (c >= 'a' && c <= 'z') X c -= 32; X X /* the final sequence... */ X c |= *tp; X X return(c); X } X X /* or the normal way */ X c = getkey(); /* get a command sequence */ X if (c == (CTRL|'X')) /* get control-x sequence */ X c = CTLX | getctl(); X return(c); X} X X/* execbuf: Execute the contents of a named buffer */ X Xexecbuf(f, n) X Xint f, n; /* default flag and numeric arg */ X X{ X register BUFFER *bp; /* ptr to buffer to execute */ X register int status; /* status return */ X char bufn[NBUFN]; /* name of buffer to execute */ X X /* find out what buffer the user wants to execute */ X if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE) X return(status); X X /* find the pointer to that buffer */ X if ((bp=bfind(bufn, TRUE, 0)) == NULL) X return(FALSE); X X /* and now execute it as asked */ X while (n-- > 0) X if ((status = dobuf(bp)) != TRUE) X return(status); X return(TRUE); X} X X/* dobuf: execute the contents of the buffer pointed to X by the passed BP */ X Xdobuf(bp) X XBUFFER *bp; /* buffer to execute */ X X{ X register int status; /* status return */ X register LINE *lp; /* pointer to line to execute */ X register LINE *hlp; /* pointer to line header */ X register int linlen; /* length of line to execute */ X register WINDOW *wp; /* ptr to windows to scan */ X char eline[NSTRING]; /* text of line to execute */ X X /* starting at the beginning of the buffer */ X hlp = bp->b_linep; X lp = hlp->l_fp; X while (lp != hlp) { X /* calculate the line length and make a local copy */ X linlen = lp->l_used; X if (linlen > NSTRING - 1) X linlen = NSTRING - 1; X strncpy(eline, lp->l_text, linlen); X eline[linlen] = 0; /* make sure it ends */ X X /* if it is not a comment, execute it */ X if (eline[0] != ';' && eline[0] != 0) { X status = docmd(eline); X if (status != TRUE) { /* a command error */ X /* look if buffer is showing */ X wp = wheadp; X while (wp != NULL) { X if (wp->w_bufp == bp) { X /* and point it */ X wp->w_dotp = lp; X wp->w_doto = 0; X wp->w_flag |= WFHARD; X } X wp = wp->w_wndp; X } X /* in any case set the buffer . */ X bp->b_dotp = lp; X bp->b_doto = 0; X return(status); X } X } X lp = lp->l_fp; /* on to the next line */ X } X return(TRUE); X} X Xexecfile(f, n) /* execute a series of commands in a file X*/ X Xint f, n; /* default flag and numeric arg to pass on to file */ X X{ X register int status; /* return status of name query */ X char *fname[NSTRING]; /* name of file to execute */ X X if ((status = mlreply("File to execute: ", fname, NSTRING -1)) != TRUE) X return(status); X X /* otherwise, execute it */ X while (n-- > 0) X if ((status=dofile(fname)) != TRUE) X return(status); X X return(TRUE); X} X X/* dofile: yank a file into a buffer and execute it X if there are no errors, delete the buffer on exit */ X Xdofile(fname) X Xchar *fname; /* file name to execute */ X X{ X register BUFFER *bp; /* buffer to place file to exeute */ X register BUFFER *cb; /* temp to hold current buf while we read */ X register int status; /* results of various calls */ X char bname[NBUFN]; /* name of buffer */ X X makename(bname, fname); /* derive the name of the buffer */ X if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */ X return(FALSE); X X bp->b_mode = MDVIEW; /* mark the buffer as read only */ X cb = curbp; /* save the old buffer */ X curbp = bp; /* make this one current */ X /* and try to read in the file to execute */ X if ((status = readin(fname, FALSE)) != TRUE) { X curbp = cb; /* restore the current buffer */ X return(status); X } X X /* go execute it! */ X curbp = cb; /* restore the current buffer */ X if ((status = dobuf(bp)) != TRUE) X return(status); X X /* if not displayed, remove the now unneeded buffer and exit */ X if (bp->b_nwnd == 0) X zotbuf(bp); X return(TRUE); X} X X X/* execute the startup file */ X Xstartup() X X{ X register int status; /* status of I/O operations */ X register int i; /* index into help file names */ X char fname[NSTRING]; /* buffer to construct file name in */ X X#if (MSDOS & LATTICE) | V7 X char *homedir; /* pointer to your home directory */ X char *getenv(); X X /* get the HOME from the environment */ X if ((homedir = getenv("HOME")) != NULL) { X /* build the file name */ X strcpy(fname, homedir); X strcat(fname, "/"); X strcat(fname, pathname[0]); X X /* and test it */ X status = ffropen(fname); X if (status == FIOSUC) { X ffclose(); X return(dofile(fname)); X } X } X#endif X X /* search through the list of startup files */ X for (i=2; i < NPNAMES; i++) { X strcpy(fname, pathname[i]); X strcat(fname, pathname[0]); X status = ffropen(fname); X if (status == FIOSUC) X break; X } X X /* if it isn't around, don't sweat it */ X if (status == FIOFNF) X return(TRUE); X X ffclose(); /* close the file to prepare for to read it in */ X X return(dofile(fname)); X} X *-*-END-of-bind.c-*-* echo x - buffer.c sed 's/^X//' >buffer.c <<'*-*-END-of-buffer.c-*-*' X/* X * Buffer management. X * Some of the functions are internal, X * and some are actually attached to user X * keys. Like everyone else, they set hints X * for the display system. X */ X#include X#include "estruct.h" X#include "edef.h" X X/* X * Attach a buffer to a window. The X * values of dot and mark come from the buffer X * if the use count is 0. Otherwise, they come X * from some other window. X */ Xusebuffer(f, n) X{ X register BUFFER *bp; X register int s; X char bufn[NBUFN]; X X if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE) X return (s); X if ((bp=bfind(bufn, TRUE, 0)) == NULL) X return (FALSE); X return(swbuffer(bp)); X} X Xnextbuffer(f, n) /* switch to the next buffer in the buffer list */ X X{ X register BUFFER *bp; X char bufn[NBUFN]; X X bp = curbp->b_bufp; X /* cycle through the buffers to find an eligable one */ X while (bp == NULL | bp->b_flag & BFTEMP) { X if (bp == NULL) X bp = bheadp; X else X bp = bp->b_bufp; X } X return(swbuffer(bp)); X} X Xswbuffer(bp) /* make buffer BP current */ X XBUFFER *bp; X X{ X register WINDOW *wp; X X if (--curbp->b_nwnd == 0) { /* Last use. */ X curbp->b_dotp = curwp->w_dotp; X curbp->b_doto = curwp->w_doto; X curbp->b_markp = curwp->w_markp; X curbp->b_marko = curwp->w_marko; X } X curbp = bp; /* Switch. */ X if (curbp->b_active != TRUE) { /* buffer not active yet*/ X /* read it in and activate it */ X readin(curbp->b_fname, TRUE); X curbp->b_dotp = lforw(curbp->b_linep); X curbp->b_doto = 0; X curbp->b_active = TRUE; X } X curwp->w_bufp = bp; X curwp->w_linep = bp->b_linep; /* For macros, ignored. */ X curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */ X if (bp->b_nwnd++ == 0) { /* First use. */ X curwp->w_dotp = bp->b_dotp; X curwp->w_doto = bp->b_doto; X curwp->w_markp = bp->b_markp; X curwp->w_marko = bp->b_marko; X return (TRUE); X } X wp = wheadp; /* Look for old. */ X while (wp != NULL) { X if (wp!=curwp && wp->w_bufp==bp) { X curwp->w_dotp = wp->w_dotp; X curwp->w_doto = wp->w_doto; X curwp->w_markp = wp->w_markp; X curwp->w_marko = wp->w_marko; X break; X } X wp = wp->w_wndp; X } X return (TRUE); X} X X/* X * Dispose of a buffer, by name. X * Ask for the name. Look it up (don't get too X * upset if it isn't there at all!). Get quite upset X * if the buffer is being displayed. Clear the buffer (ask X * if the buffer has been changed). Then free the header X * line and the buffer header. Bound to "C-X K". X */ Xkillbuffer(f, n) X X{ X register BUFFER *bp; X register int s; X char bufn[NBUFN]; X X if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE) X return(s); X if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown. */ X return (TRUE); X return(zotbuf(bp)); X} X Xzotbuf(bp) /* kill the buffer pointed to by bp */ X Xregister BUFFER *bp; X X{ X register BUFFER *bp1; X register BUFFER *bp2; X register int s; X X if (bp->b_nwnd != 0) { /* Error if on screen. */ X mlwrite("Buffer is being displayed"); X return (FALSE); X } X if ((s=bclear(bp)) != TRUE) /* Blow text away. */ X return (s); X free((char *) bp->b_linep); /* Release header line. */ X bp1 = NULL; /* Find the header. */ X bp2 = bheadp; X while (bp2 != bp) { X bp1 = bp2; X bp2 = bp2->b_bufp; X } X bp2 = bp2->b_bufp; /* Next one in chain. */ X if (bp1 == NULL) /* Unlink it. */ X bheadp = bp2; X else X bp1->b_bufp = bp2; X free((char *) bp); /* Release buffer block */ X return (TRUE); X} X Xnamebuffer(f,n) /* Rename the current buffer */ X Xint f, n; /* default Flag & Numeric arg */ X X{ X register BUFFER *bp; /* pointer to scan through all buffers */ X char bufn[NBUFN]; /* buffer to hold buffer name */ X X /* prompt for and get the new buffer name */ Xask: if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE) X return(FALSE); X X /* and check for duplicates */ X bp = bheadp; X while (bp != NULL) { X if (bp != curbp) { X /* if the names the same */ X if (strcmp(bufn, bp->b_bname) == 0) X goto ask; /* try again */ X } X bp = bp->b_bufp; /* onward */ X } X X strcpy(curbp->b_bname, bufn); /* copy buffer name to structure */ X curwp->w_flag |= WFMODE; /* make mode line replot */ X mlerase(); X} X X/* X * List all of the active X * buffers. First update the special X * buffer that holds the list. Next make X * sure at least 1 window is displaying the X * buffer list, splitting the screen if this X * is what it takes. Lastly, repaint all of X * the windows that are displaying the X * list. Bound to "C-X C-B". X */ Xlistbuffers(f, n) X{ X register WINDOW *wp; X register BUFFER *bp; X register int s; X X if ((s=makelist()) != TRUE) X return (s); X if (blistp->b_nwnd == 0) { /* Not on screen yet. */ X if ((wp=wpopup()) == NULL) X return (FALSE); X bp = wp->w_bufp; X if (--bp->b_nwnd == 0) { X bp->b_dotp = wp->w_dotp; X bp->b_doto = wp->w_doto; X bp->b_markp = wp->w_markp; X bp->b_marko = wp->w_marko; X } X wp->w_bufp = blistp; X ++blistp->b_nwnd; X } X wp = wheadp; X while (wp != NULL) { X if (wp->w_bufp == blistp) { X wp->w_linep = lforw(blistp->b_linep); X wp->w_dotp = lforw(blistp->b_linep); X wp->w_doto = 0; X wp->w_markp = NULL; X wp->w_marko = 0; X wp->w_flag |= WFMODE|WFHARD; X } X wp = wp->w_wndp; X } X return (TRUE); X} X X/* X * This routine rebuilds the X * text in the special secret buffer X * that holds the buffer list. It is called X * by the list buffers command. Return TRUE X * if everything works. Return FALSE if there X * is an error (if there is no memory). X */ Xmakelist() X{ X register char *cp1; X register char *cp2; X register int c; X register BUFFER *bp; X register LINE *lp; X register int nbytes; X register int s; X register int i; X register int type; X char b[6+1]; X char line[128]; X X blistp->b_flag &= ~BFCHG; /* Don't complain! */ X if ((s=bclear(blistp)) != TRUE) /* Blow old text away */ X return (s); X strcpy(blistp->b_fname, ""); X if (addline("AC MODES Size Buffer File") == FALSE X || addline("-- ----- ---- ------ ----") == FALSE) X return (FALSE); X bp = bheadp; /* For all buffers */ X X /* build line to report global mode settings */ X cp1 = &line[0]; X *cp1++ = ' '; X *cp1++ = ' '; X *cp1++ = ' '; X X /* output the mode codes */ X for (i = 0; i < NUMMODES; i++) X if (gmode & (1 << i)) X *cp1++ = modecode[i]; X else X *cp1++ = '.'; X strcpy(cp1, " Global Modes"); X if (addline(line) == FALSE) X return(FALSE); X X /* output the list of buffers */ X while (bp != NULL) { X if ((bp->b_flag&BFTEMP) != 0) { /* Skip magic ones. */ X bp = bp->b_bufp; X continue; X } X cp1 = &line[0]; /* Start at left edge */ X X /* output status of ACTIVE flag (has the file been read in? */ X if (bp->b_active == TRUE) /* "@" if activated */ X *cp1++ = '@'; X else X *cp1++ = ' '; X X /* output status of changed flag */ X if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */ X *cp1++ = '*'; X else X *cp1++ = ' '; X *cp1++ = ' '; /* Gap. */ X X /* output the mode codes */ X for (i = 0; i < NUMMODES; i++) { X if (bp->b_mode & (1 << i)) X *cp1++ = modecode[i]; X else X *cp1++ = '.'; X } X *cp1++ = ' '; /* Gap. */ X nbytes = 0; /* Count bytes in buf. */ X lp = lforw(bp->b_linep); X while (lp != bp->b_linep) { X nbytes += llength(lp)+1; X lp = lforw(lp); X } X itoa(b, 6, nbytes); /* 6 digit buffer size. */ X cp2 = &b[0]; X while ((c = *cp2++) != 0) X *cp1++ = c; X *cp1++ = ' '; /* Gap. */ X cp2 = &bp->b_bname[0]; /* Buffer name */ X while ((c = *cp2++) != 0) X *cp1++ = c; X cp2 = &bp->b_fname[0]; /* File name */ X if (*cp2 != 0) { X while (cp1 < &line[2+1+5+1+6+1+NBUFN]) X *cp1++ = ' '; X while ((c = *cp2++) != 0) { X if (cp1 < &line[128-1]) X *cp1++ = c; X } X } X *cp1 = 0; /* Add to the buffer. */ X if (addline(line) == FALSE) X return (FALSE); X bp = bp->b_bufp; X } X return (TRUE); /* All done */ X} X Xitoa(buf, width, num) Xregister char buf[]; Xregister int width; Xregister int num; X{ X buf[width] = 0; /* End of string. */ X while (num >= 10) { /* Conditional digits. */ X buf[--width] = (num%10) + '0'; X num /= 10; X } X buf[--width] = num + '0'; /* Always 1 digit. */ X while (width != 0) /* Pad with blanks. */ X buf[--width] = ' '; X} X X/* X * The argument "text" points to X * a string. Append this line to the X * buffer list buffer. Handcraft the EOL X * on the end. Return TRUE if it worked and X * FALSE if you ran out of room. X */ Xaddline(text) Xchar *text; X{ X register LINE *lp; X register int i; X register int ntext; X X ntext = strlen(text); X if ((lp=lalloc(ntext)) == NULL) X return (FALSE); X for (i=0; ib_linep->l_bp->l_fp = lp; /* Hook onto the end */ X lp->l_bp = blistp->b_linep->l_bp; X blistp->b_linep->l_bp = lp; X lp->l_fp = blistp->b_linep; X if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */ X blistp->b_dotp = lp; /* move it to new line */ X return (TRUE); X} X X/* X * Look through the list of X * buffers. Return TRUE if there X * are any changed buffers. Buffers X * that hold magic internal stuff are X * not considered; who cares if the X * list of buffer names is hacked. X * Return FALSE if no buffers X * have been changed. X */ Xanycb() X{ X register BUFFER *bp; X X bp = bheadp; X while (bp != NULL) { X if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0) X return (TRUE); X bp = bp->b_bufp; X } X return (FALSE); X} X X/* X * Find a buffer, by name. Return a pointer X * to the BUFFER structure associated with it. If X * the named buffer is found, but is a TEMP buffer (like X * the buffer list) conplain. If the buffer is not found X * and the "cflag" is TRUE, create it. The "bflag" is X * the settings for the flags in in buffer. X */ XBUFFER * Xbfind(bname, cflag, bflag) Xregister char *bname; X{ X register BUFFER *bp; X register BUFFER *sb; /* buffer to insert after */ X register LINE *lp; X char *malloc(); X X bp = bheadp; X while (bp != NULL) { X if (strcmp(bname, bp->b_bname) == 0) { X if ((bp->b_flag&BFTEMP) != 0) { X mlwrite("Cannot select builtin buffer"); X return (NULL); X } X return (bp); X } X bp = bp->b_bufp; X } X if (cflag != FALSE) { X if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) X return (NULL); X if ((lp=lalloc(0)) == NULL) { X free((char *) bp); X return (NULL); X } X /* find the place in the list to insert this buffer */ X if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) { X /* insert at the begining */ X bp->b_bufp = bheadp; X bheadp = bp; X } else { X sb = bheadp; X while (sb->b_bufp != NULL) { X if (strcmp(sb->b_bufp->b_bname, bname) > 0) X break; X sb = sb->b_bufp; X } X X /* and insert it */ X bp->b_bufp = sb->b_bufp; X sb->b_bufp = bp; X } X X /* and set up the other buffer fields */ X bp->b_active = TRUE; X bp->b_dotp = lp; X bp->b_doto = 0; X bp->b_markp = NULL; X bp->b_marko = 0; X bp->b_flag = bflag; X bp->b_mode = gmode; X bp->b_nwnd = 0; X bp->b_linep = lp; X strcpy(bp->b_fname, ""); X strcpy(bp->b_bname, bname); X lp->l_fp = lp; X lp->l_bp = lp; X } X return (bp); X} X X/* X * This routine blows away all of the text X * in a buffer. If the buffer is marked as changed X * then we ask if it is ok to blow it away; this is X * to save the user the grief of losing text. The X * window chain is nearly always wrong if this gets X * called; the caller must arrange for the updates X * that are required. Return TRUE if everything X * looks good. X */ Xbclear(bp) Xregister BUFFER *bp; X{ X register LINE *lp; X register int s; X X if ((bp->b_flag&BFTEMP) == 0 /* Not scratch buffer. */ X && (bp->b_flag&BFCHG) != 0 /* Something changed */ X && (s=mlyesno("Discard changes")) != TRUE) X return (s); X bp->b_flag &= ~BFCHG; /* Not changed */ X while ((lp=lforw(bp->b_linep)) != bp->b_linep) X lfree(lp); X bp->b_dotp = bp->b_linep; /* Fix "." */ X bp->b_doto = 0; X bp->b_markp = NULL; /* Invalidate "mark" */ X bp->b_marko = 0; X return (TRUE); X} *-*-END-of-buffer.c-*-* echo x - fileio.c sed 's/^X//' >fileio.c <<'*-*-END-of-fileio.c-*-*' X/* X * The routines in this file read and write ASCII files from the disk. All of X * the knowledge about files are here. A better message writing scheme should X * be used. X */ X#include X#include "estruct.h" X#include "edef.h" X XFILE *ffp; /* File pointer, all functions. */ X X/* X * Open a file for reading. X */ Xffropen(fn) Xchar *fn; X{ X if ((ffp=fopen(fn, "r")) == NULL) X return (FIOFNF); X return (FIOSUC); X} X X/* X * Open a file for writing. Return TRUE if all is well, and FALSE on error X * (cannot create). X */ Xffwopen(fn) Xchar *fn; X{ X#if VMS X register int fd; X X if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0 X || (ffp=fdopen(fd, "w")) == NULL) { X#else X if ((ffp=fopen(fn, "w")) == NULL) { X#endif X mlwrite("Cannot open file for writing"); X return (FIOERR); X } X return (FIOSUC); X} X X/* X * Close a file. Should look at the status in all systems. X */ Xffclose() X{ X#if MSDOS X fputc(26, ffp); /* add a ^Z at the end of the file */ X#endif X X#if V7 | (MSDOS & LATTICE) X if (fclose(ffp) != FALSE) { X mlwrite("Error closing file"); X return(FIOERR); X } X return(FIOSUC); X#else X fclose(ffp); X return (FIOSUC); X#endif X} X X/* X * Write a line to the already opened file. The "buf" points to the buffer, X * and the "nbuf" is its length, less the free newline. Return the status. X * Check only at the newline. X */ Xffputline(buf, nbuf) Xchar buf[]; X{ X register int i; X X for (i = 0; i < nbuf; ++i) X fputc(buf[i]&0xFF, ffp); X X fputc('\n', ffp); X X if (ferror(ffp)) { X mlwrite("Write I/O error"); X return (FIOERR); X } X X return (FIOSUC); X} X X/* X * Read a line from a file, and store the bytes in the supplied buffer. The X * "nbuf" is the length of the buffer. Complain about long lines and lines X * at the end of the file that don't have a newline present. Check for I/O X * errors too. Return status. X */ Xffgetline(buf, nbuf) Xregister char buf[]; X{ X register int c; X register int i; X X i = 0; X X while ((c = fgetc(ffp)) != EOF && c != '\n') { X if (i >= nbuf-2) { X buf[nbuf - 2] = c; /* store last char read */ X buf[nbuf - 1] = 0; /* and terminate it */ X mlwrite("File has long line"); X return (FIOLNG); X } X buf[i++] = c; X } X X if (c == EOF) { X if (ferror(ffp)) { X mlwrite("File read error"); X return (FIOERR); X } X X if (i != 0) { X mlwrite("File has funny line at EOF"); X return (FIOERR); X } X return (FIOEOF); X } X X buf[i] = 0; X return (FIOSUC); X} *-*-END-of-fileio.c-*-* echo x - hp150.c sed 's/^X//' >hp150.c <<'*-*-END-of-hp150.c-*-*' X/* X * The routines in this file provide support for HP150 screens X * and routines to access the Keyboard through KEYCODE mode. X * It compiles into nothing if not an HP150 screen device. X * added by Daniel Lawrence X */ X X#define termdef 1 /* don't define "term" external */ X X#include X#include "estruct.h" X#include "edef.h" X X#if HP150 X X#include X X#define NROW 24 /* Screen size. */ X#define NCOL 80 /* Edit if you want to. */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X#define BEL 0x07 /* BEL character. */ X#define ESC 0x1B /* ESC character. */ X Xextern int openhp(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int closehp(); Xextern int hp15move(); Xextern int hp15eeol(); Xextern int hp15eeop(); Xextern int hp15beep(); Xextern int gethpkey(); Xextern int hp15rev(); X X/* weird to ascii translation table */ X Xchar trans[][2] = { X 0x24, 9, /* tab */ X 0x25, 13, /* ret */ X 0x27, 8, /* backspace */ X 0x30, 48, /* zero */ X 0x31, 49, /* one */ X 0x32, 50, /* two */ X 0x33, 51, /* three */ X 0x34, 52, /* four */ X 0x35, 53, /* five */ X 0x36, 54, /* six */ X 0x37, 55, /* seven */ X 0x38, 56, /* eight */ X 0x39, 57, /* nine */ X 0x50, 13, /* enter */ X 0x54, 27, /* break -> ESC */ X 0x55, 27, /* esc */ X 0x58, 24, /* stop -> ^X */ X 0x70, 45, /* N-minus */ X 0x71, 42, /* N-asterisk */ X 0x72, 43, /* N-plus */ X 0x73, 47, /* N-slash */ X 0x74, 44, /* N-comma */ X 0x75, 13, /* N-enter */ X 0x76, 9, /* N-tab */ X 0x77, 46 /* N-period */ X}; X X#define NTRANS sizeof(trans) / 2 X Xunion REGS r; /* register set for bios and dos (AGIOS) calls */ Xint capslock = 0; /* caps lock flag */ X X/* X * Standard terminal interface dispatch table. Most of the fields point into X * "termio" code. X */ XTERM term = { X NROW-1, X NCOL, X MARGIN, X SCRSIZ, X openhp, X closehp, X gethpkey, X ttputc, X ttflush, X hp15move, X hp15eeol, X hp15eeop, X hp15beep, X hp15rev X}; X Xhp15move(row, col) X{ X ttputc(ESC); X ttputc('&'); X ttputc('a'); X hp15parm(col); X ttputc('c'); X hp15parm(row); X ttputc('R'); X} X Xhp15eeol() X{ X ttputc(ESC); X ttputc('K'); X} X Xhp15eeop() X{ X ttputc(ESC); X ttputc('J'); X} X Xhp15rev(status) /* change the reverse video status */ X Xint status; /* TRUE = on, FALSE = off */ X X{ X ttputc(ESC); X ttputc('&'); X ttputc('d'); X ttputc(status ? 'B': '@'); X} X Xhp15beep() X{ X ttputc(BEL); X ttflush(); X} X Xhp15parm(n) Xregister int n; X{ X register int q; X X q = n/10; X if (q != 0) X hp15parm(q); X ttputc((n%10) + '0'); X} X X Xgethpkey() /* get a key from the HP keyboard while in keycode mode */ X X{ X static int keepflag = 0; /* kept ahead char flag */ X static int keepchar = 0; /* kept ehead flag */ X int c; X int devid; /* device ID */ X int ctype; /* type of character gotten */ X int shiftb; /* state of shift keys */ X int i; X X /* if we are in an extended char sequence, finish it */ X if (keepflag != 0) { X keepflag = 0; X return(keepchar); X } X X /* grab the next 4 char sequence */ Xnext: shiftb = ttgetc(); X devid = ttgetc(); X c = ttgetc(); X ttgetc(); /* skip null byte */ X X /* make sure we are from the keyboard */ X if (devid != 192) X goto next; X X /* if normal ascii, return it */ X if ((shiftb & 0x80) == 0) { X if (capslock && c >= 'a' && c <= 'z') X c -= 32; X return(c); X } X X /* check specifically for the caps lock key */ X if (c == 0x56) { X capslock = ~capslock; X goto next; X } X X /* check to see if it needs translation */ X for (i=0; i < NTRANS; i++) X if (trans[i][0] == c) X return((int)trans[i][1]); X X /* other wise, shove it in the keep char and return the leadin code */ X keepchar = c; X keepflag = 1; X return(0); X} X Xopenhp() /* open the HP150 keyboard for input */ X X{ X revexist = TRUE; X X /* define key charectoristics with AGIOS call (0, 40) */ X defkey(); X X /* Turn on RAW mode with MSDOS call 44h */ X rawon(); X X /* Turn off Control-C checking MS-DOS 33h */ X ckeyoff(); X X /* Turn on keycode mode with AGIOS call (0,43) */ X keycon(); X} X Xclosehp() /* close the HP150 keyboard for input */ X X{ X /* define key charectoristics with AGIOS call (0, 40) */ X undefkey(); X X /* Turn off RAW mode with MSDOS call 44h */ X rawoff(); X X /* Turn on Control-C checking MS-DOS 33h */ X ckeyon(); X X /* Turn off keycode mode with AGIOS call (0,43) */ X keycoff(); X} X Xrawon() /* put the HP150 keyboard into RAW mode */ X X{ X /* get the IO control info */ X X r.x.ax = 0x4400; /* IO ctrl get device information */ X r.x.bx = 0x0001; /* File handle; 1 for console */ X intdos(&r, &r); /* go fer it */ X X r.h.dh = 0; /* clear high byte for put */ X r.h.dl |= 0x20; /* set raw bit */ X X /* and put it back */ X X r.x.ax = 0x4401; /* IO ctrl put device information */ X r.x.bx = 0x0001; /* File handle; 1 for console */ X intdos(&r, &r); /* go fer it */ X} X Xrawoff() /* put the HP150 keyboard into COOKED mode */ X X{ X /* get the IO control info */ X X r.x.ax = 0x4400; /* IO ctrl get device information */ X r.x.bx = 0x0001; /* File handle; 1 for console */ X intdos(&r, &r); /* go fer it */ X X r.h.dh = 0; /* clear high byte for put */ X r.h.dl &= 0xdf; /* set raw bit */ X X /* and put it back */ X X r.x.ax = 0x4401; /* IO ctrl put device information */ X r.x.bx = 0x0001; /* File handle; 1 for console */ X intdos(&r, &r); /* go fer it */ X} X X Xckeyoff() /* turn control-C trapping off */ X X{ X r.h.ah = 0x33; /* ctrl-break check */ X r.h.al = 1; /* set the state of the ctrl-break check */ X r.h.dl = 0; /* turn it off */ X intdos(&r, &r); X} X Xckeyon() /* turn control-C trapping on */ X X{ X r.h.ah = 0x33; /* ctrl-break check */ X r.h.al = 1; /* set the state of the ctrl-break check */ X r.h.dl = 1; /* turn it on */ X intdos(&r, &r); X} X Xagios(buf, len) /* perform an AGIOS call */ X Xchar *buf; /* sequence of bytes in command */ Xint len; /* length of command in bytes */ X X{ X r.x.ax = 0x4403; /* I/O ctrl write */ X r.x.bx = 1; /* console handle */ X r.x.cx = len; /* buffer length */ X r.x.dx = (unsigned)buf; /* buffer address */ X return(intdos(&r, &r)); /* do it */ X} X Xkeycon() /* turn keycode mode on */ X X{ X static char cmd[] = {43, 0, 1}; X X return(agios(&cmd[0], 3)); X} X Xkeycoff() /* turn keycode mode off */ X X{ X static char cmd[] = {43, 0, 0}; X X return(agios(&cmd[0], 3)); X} X Xdefkey() /* change all special keys to intercept mode */ X X{ X static char cmd[] = {40, 0, 2, 0, 0xfe, 0}; X X return(agios(&cmd[0], 6)); X} X Xundefkey() /* change all special keys to intercept mode */ X X{ X static char cmd[] = {40, 0, 0, 0, 0xfe, 0}; X X return(agios(&cmd[0], 6)); X} X X#else X Xh15hello() X X{ X} X#endif *-*-END-of-hp150.c-*-* echo x - lock.c sed 's/^X//' >lock.c <<'*-*-END-of-lock.c-*-*' X/* LOCK: File locking command routines for MicroEMACS X written by Daniel Lawrence X */ X X#include X#include "estruct.h" X#include "edef.h" X X#if FILOCK X#if V7 & BSD X#include X Xextern int sys_nerr; /* number of system error messages defined */ Xextern char *sys_errlist[]; /* list of message texts */ Xextern int errno; /* current error */ X Xchar *lname[NLOCKS]; /* names of all locked files */ Xint numlocks; /* # of current locks active */ X X/* lockchk: check a file for locking and add it to the list */ X Xlockchk(fname) X Xchar *fname; /* file to check for a lock */ X X{ X register int i; /* loop indexes */ X register int status; /* return status */ X char *undolock(); X X /* check to see if that file is already locked here */ X if (numlocks > 0) X for (i=0; i < numlocks; ++i) X if (strcmp(fname, lname[i]) == 0) X return(TRUE); X X /* if we have a full locking table, bitch and leave */ X if (numlocks == NLOCKS) { X mlwrite("LOCK ERROR: Lock table full"); X return(ABORT); X } X X /* next, try to lock it */ X status = lock(fname); X if (status == ABORT) /* file is locked, no override */ X return(ABORT); X if (status == FALSE) /* locked, overriden, dont add to table */ X return(TRUE); X X /* we have now locked it, add it to our table */ X lname[++numlocks - 1] = (char *)malloc(strlen(fname) + 1); X if (lname[numlocks - 1] == NULL) { /* malloc failure */ X undolock(fname); /* free the lock */ X mlwrite("Cannot lock, out of memory"); X --numlocks; X return(ABORT); X } X X /* everthing is cool, add it to the table */ X strcpy(lname[numlocks-1], fname); X return(TRUE); X} X X/* lockrel: release all the file locks so others may edit */ X Xlockrel() X X{ X register int i; /* loop index */ X register int status; /* status of locks */ X register int s; /* status of one unlock */ X X status = TRUE; X if (numlocks > 0) X for (i=0; i < numlocks; ++i) { X if ((s = unlock(lname[i])) != TRUE) X status = s; X free(lname[i]); X } X numlocks = 0; X return(status); X} X X/* lock: Check and lock a file from access by others X returns TRUE = files was not locked and now is X FALSE = file was locked and overridden X ABORT = file was locked, abort command X*/ X Xlock(fname) X Xchar *fname; /* file name to lock */ X X{ X register char *locker; /* lock error message */ X register int status; /* return status */ X char msg[NSTRING]; /* message string */ X char *dolock(); X X /* attempt to lock the file */ X locker = dolock(fname); X if (locker == NULL) /* we win */ X return(TRUE); X X /* file failed...abort */ X if (strncmp(locker, "LOCK", 4) == 0) { X lckerror(locker); X return(ABORT); X } X X /* someone else has it....override? */ X strcpy(msg, "File in use by "); X strcat(msg, locker); X strcat(msg, ", overide?"); X status = mlyesno(msg); /* ask them */ X if (status == TRUE) X return(FALSE); X else X return(ABORT); X} X X/* unlock: Unlock a file X this only warns the user if it fails X */ X Xunlock(fname) X Xchar *fname; /* file to unlock */ X X{ X register char *locker; /* undolock return string */ X char *undolock(); X X /* unclock and return */ X locker = undolock(fname); X if (locker == NULL) X return(TRUE); X X /* report the error and come back */ X lckerror(locker); X return(FALSE); X} X Xlckerror(errstr) /* report a lock error */ X Xchar *errstr; /* lock error string to print out */ X X{ X char obuf[NSTRING]; /* output buffer for error message */ X X strcpy(obuf, errstr); X strcat(obuf, " - "); X if (errno < sys_nerr) X strcat(obuf, sys_errlist[errno]); X else X strcat(obuf, "[can not get system error message]"); X mlwrite(obuf); X} X#endif X#else Xlckhello() /* dummy function */ X{ X} X#endif *-*-END-of-lock.c-*-* exit