home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / uemacs3.6 / part4 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  49.7 KB

  1. Subject: MicroEMACS 3.6 (Part 4 of 8)
  2. Newsgroups: mod.sources
  3. Approved: jpn@panda.UUCP
  4.  
  5. Mod.sources:  Volume 4, Issue 101
  6. Submitted by: ihnp4!itivax!duncan!lawrence
  7.  
  8. echo x - bind.c
  9. sed 's/^X//' >bind.c <<'*-*-END-of-bind.c-*-*'
  10. X/*    This file is for functions having to do with key bindings,
  11. X    descriptions, help commands, and command line execution.
  12. X
  13. X    written 11-feb-86 by Daniel Lawrence
  14. X                                */
  15. X
  16. X#include    <stdio.h>
  17. X#include    "estruct.h"
  18. X#include    "edef.h"
  19. X#include    "epath.h"
  20. X
  21. Xdeskey(f, n)    /* describe the command for a certain key */
  22. X{
  23. X    register int c;        /* command character to describe */
  24. X    register char *ptr;    /* string pointer to scan output strings */
  25. X    register KEYTAB *ktp;    /* pointer into the command table */
  26. X    register int found;    /* matched command flag */
  27. X    register NBIND *nptr;    /* pointer into the name binding table */
  28. X    char outseq[80];    /* output buffer for command sequence */
  29. X
  30. X    /* prompt the user to type us a key to describe */
  31. X    mlwrite(": describe-key ");
  32. X
  33. X    /* get the command sequence to describe */
  34. X    c = getckey();            /* get a command sequence */
  35. X
  36. X    /* change it to something we can print as well */
  37. X    cmdstr(c, &outseq[0]);
  38. X
  39. X    /* and dump it out */
  40. X    ptr = &outseq[0];
  41. X    while (*ptr)
  42. X        (*term.t_putchar)(*ptr++);
  43. X    (*term.t_putchar)(' ');        /* space it out */
  44. X
  45. X    /* find the right ->function */
  46. X    ktp = &keytab[0];
  47. X    found = FALSE;
  48. X    while (ktp->k_fp != NULL) {
  49. X        if (ktp->k_code == c) {
  50. X            found = TRUE;
  51. X            break;
  52. X        }
  53. X        ++ktp;
  54. X    }
  55. X
  56. X    if (!found)
  57. X        strcpy(outseq,"Not Bound");
  58. X    else {
  59. X        /* match it against the name binding table */
  60. X        nptr = &names[0];
  61. X        strcpy(outseq,"[Bad binding]");
  62. X        while (nptr->n_func != NULL) {
  63. X            if (nptr->n_func == ktp->k_fp) {
  64. X                strcpy(outseq, nptr->n_name);
  65. X                break;
  66. X            }
  67. X            ++nptr;
  68. X        }
  69. X    }
  70. X
  71. X    /* output the command sequence */
  72. X    ptr = &outseq[0];
  73. X    while (*ptr)
  74. X        (*term.t_putchar)(*ptr++);
  75. X}
  76. X
  77. Xcmdstr(c, seq)    /* change a key command to a string we can print out */
  78. X
  79. Xint c;        /* sequence to translate */
  80. Xchar *seq;    /* destination string for sequence */
  81. X
  82. X{
  83. X    char *ptr;    /* pointer into current position in sequence */
  84. X
  85. X    ptr = seq;
  86. X
  87. X    /* apply meta sequence if needed */
  88. X    if (c & META) {
  89. X        *ptr++ = 'M';
  90. X        *ptr++ = '-';
  91. X    }
  92. X
  93. X    /* apply ^X sequence if needed */
  94. X    if (c & CTLX) {
  95. X        *ptr++ = '^';
  96. X        *ptr++ = 'X';
  97. X    }
  98. X
  99. X    /* apply SPEC sequence if needed */
  100. X    if (c & SPEC) {
  101. X        *ptr++ = 'F';
  102. X        *ptr++ = 'N';
  103. X    }
  104. X
  105. X    /* apply control sequence if needed */
  106. X    if (c & CTRL) {
  107. X        *ptr++ = '^';
  108. X    }
  109. X
  110. X    c = c & 255;    /* strip the prefixes */
  111. X
  112. X    /* and output the final sequence */
  113. X
  114. X    *ptr++ = c;
  115. X    *ptr = 0;    /* terminate the string */
  116. X}
  117. X
  118. Xhelp(f, n)    /* give me some help!!!!
  119. X           bring up a fake buffer and read the help file
  120. X           into it with view mode            */
  121. X{
  122. X    register int status;    /* status of I/O operations */
  123. X    register WINDOW *wp;    /* scnaning pointer to windows */
  124. X    register int i;        /* index into help file names */
  125. X    char fname[NSTRING];    /* buffer to construct file name in */
  126. X
  127. X    /* search through the list of help files */
  128. X    for (i=2; i < NPNAMES; i++) {
  129. X        strcpy(fname, pathname[i]);
  130. X        strcat(fname, pathname[1]);
  131. X        status = ffropen(fname);
  132. X        if (status == FIOSUC)
  133. X            break;
  134. X    }
  135. X
  136. X    if (status == FIOFNF) {
  137. X        mlwrite("[Help file is not online]");
  138. X        return(FALSE);
  139. X    }
  140. X    ffclose();    /* close the file to prepare for to read it in */
  141. X
  142. X    /* split the current window to make room for the help stuff */
  143. X    if (splitwind(FALSE, 1) == FALSE)
  144. X            return(FALSE);
  145. X
  146. X    /* and read the stuff in */
  147. X    if (getfile(fname, FALSE) == FALSE)
  148. X        return(FALSE);
  149. X
  150. X    /* make this window in VIEW mode, update all mode lines */
  151. X    curwp->w_bufp->b_mode |= MDVIEW;
  152. X    wp = wheadp;
  153. X    while (wp != NULL) {
  154. X        wp->w_flag |= WFMODE;
  155. X        wp = wp->w_wndp;
  156. X    }
  157. X    return(TRUE);
  158. X}
  159. X
  160. Xint (*fncmatch(fname))() /* match fname to a function in the names table
  161. X                and return any match or NULL if none        */
  162. X
  163. Xchar *fname;    /* name to attempt to match */
  164. X
  165. X{
  166. X    register NBIND *ffp;    /* pointer to entry in name binding table */
  167. X
  168. X    /* scan through the table, returning any match */
  169. X    ffp = &names[0];
  170. X    while (ffp->n_func != NULL) {
  171. X        if (strcmp(fname, ffp->n_name) == 0)
  172. X            return(ffp->n_func);
  173. X        ++ffp;
  174. X    }
  175. X    return(NULL);
  176. X}
  177. X
  178. X/* bindtokey:    add a new key to the key binding table
  179. X*/
  180. X
  181. Xbindtokey(f, n)
  182. X
  183. Xint f, n;    /* command arguments [IGNORED] */
  184. X
  185. X{
  186. X    register int c;        /* command key to bind */
  187. X    register (*kfunc)();    /* ptr to the requexted function to bind to */
  188. X    register char *ptr;    /* ptr to dump out input key string */
  189. X    register KEYTAB *ktp;    /* pointer into the command table */
  190. X    register int found;    /* matched command flag */
  191. X    char outseq[80];    /* output buffer for keystroke sequence */
  192. X    int (*getname())();
  193. X
  194. X    /* prompt the user to type in a key to bind */
  195. X    mlwrite(": bind-to-key ");
  196. X
  197. X    /* get the function name to bind it to */
  198. X    kfunc = getname();
  199. X    if (kfunc == NULL) {
  200. X        mlwrite("[No such function]");
  201. X        return(FALSE);
  202. X    }
  203. X    (*term.t_putchar)(' ');        /* space it out */
  204. X    (*term.t_flush)();
  205. X
  206. X    /* get the command sequence to bind */
  207. X    c = getckey();            /* get a command sequence */
  208. X
  209. X    /* change it to something we can print as well */
  210. X    cmdstr(c, &outseq[0]);
  211. X
  212. X    /* and dump it out */
  213. X    ptr = &outseq[0];
  214. X    while (*ptr)
  215. X        (*term.t_putchar)(*ptr++);
  216. X
  217. X    /* search the table to see if it exists */
  218. X    ktp = &keytab[0];
  219. X    found = FALSE;
  220. X    while (ktp->k_fp != NULL) {
  221. X        if (ktp->k_code == c) {
  222. X            found = TRUE;
  223. X            break;
  224. X        }
  225. X        ++ktp;
  226. X    }
  227. X
  228. X    if (found) {    /* it exists, just change it then */
  229. X        ktp->k_fp = kfunc;
  230. X    } else {    /* otherwise we need to add it to the end */
  231. X        /* if we run out of binding room, bitch */
  232. X        if (ktp >= &keytab[NBINDS]) {
  233. X            mlwrite("Binding table FULL!");
  234. X            return(FALSE);
  235. X        }
  236. X
  237. X        ktp->k_code = c;    /* add keycode */
  238. X        ktp->k_fp = kfunc;    /* and the function pointer */
  239. X        ++ktp;            /* and make sure the next is null */
  240. X        ktp->k_code = 0;
  241. X        ktp->k_fp = NULL;
  242. X    }
  243. X
  244. X    return(TRUE);
  245. X}
  246. X
  247. X/* unbindkey:    delete a key from the key binding table
  248. X*/
  249. X
  250. Xunbindkey(f, n)
  251. X
  252. Xint f, n;    /* command arguments [IGNORED] */
  253. X
  254. X{
  255. X    register int c;        /* command key to unbind */
  256. X    register char *ptr;    /* ptr to dump out input key string */
  257. X    register KEYTAB *ktp;    /* pointer into the command table */
  258. X    register KEYTAB *sktp;    /* saved pointer into the command table */
  259. X    register int found;    /* matched command flag */
  260. X    char outseq[80];    /* output buffer for keystroke sequence */
  261. X
  262. X    /* prompt the user to type in a key to unbind */
  263. X    mlwrite(": unbind-key ");
  264. X
  265. X    /* get the command sequence to unbind */
  266. X    c = getckey();            /* get a command sequence */
  267. X
  268. X    /* change it to something we can print as well */
  269. X    cmdstr(c, &outseq[0]);
  270. X
  271. X    /* and dump it out */
  272. X    ptr = &outseq[0];
  273. X    while (*ptr)
  274. X        (*term.t_putchar)(*ptr++);
  275. X
  276. X    /* search the table to see if the key exists */
  277. X    ktp = &keytab[0];
  278. X    found = FALSE;
  279. X    while (ktp->k_fp != NULL) {
  280. X        if (ktp->k_code == c) {
  281. X            found = TRUE;
  282. X            break;
  283. X        }
  284. X        ++ktp;
  285. X    }
  286. X
  287. X    /* if it isn't bound, bitch */
  288. X    if (!found) {
  289. X        mlwrite("[Key not bound]");
  290. X        return(FALSE);
  291. X    }
  292. X
  293. X    /* save the pointer and scan to the end of the table */
  294. X    sktp = ktp;
  295. X    while (ktp->k_fp != NULL)
  296. X        ++ktp;
  297. X    --ktp;        /* backup to the last legit entry */
  298. X
  299. X    /* copy the last entry to the current one */
  300. X    sktp->k_code = ktp->k_code;
  301. X    sktp->k_fp   = ktp->k_fp;
  302. X
  303. X    /* null out the last one */
  304. X    ktp->k_code = 0;
  305. X    ktp->k_fp = NULL;
  306. X    return(TRUE);
  307. X}
  308. X
  309. X/* namedcmd:    execute a named command even if it is not bound
  310. X*/
  311. X
  312. Xnamedcmd(f, n)
  313. X
  314. Xint f, n;    /* command arguments [passed through to command executed] */
  315. X
  316. X{
  317. X    register (*kfunc)();    /* ptr to the requexted function to bind to */
  318. X    int (*getname())();
  319. X
  320. X    /* prompt the user to type a named command */
  321. X    mlwrite(": ");
  322. X
  323. X    /* and now get the function name to execute */
  324. X    kfunc = getname();
  325. X    if (kfunc == NULL) {
  326. X        mlwrite("[No such function]");
  327. X        return(FALSE);
  328. X    }
  329. X
  330. X    /* and then execute the command */
  331. X    return((*kfunc)(f, n));
  332. X}
  333. X
  334. Xdesbind(f, n)    /* describe bindings
  335. X           bring up a fake buffer and list the key bindings
  336. X           into it with view mode            */
  337. X{
  338. X    register WINDOW *wp;    /* scnaning pointer to windows */
  339. X    register KEYTAB *ktp;    /* pointer into the command table */
  340. X    register NBIND *nptr;    /* pointer into the name binding table */
  341. X    register BUFFER *bp;    /* buffer to put binding list into */
  342. X    char *strp;        /* pointer int string to send */
  343. X    int cpos;        /* current position to use in outseq */
  344. X    char outseq[80];    /* output buffer for keystroke sequence */
  345. X
  346. X    /* split the current window to make room for the binding list */
  347. X    if (splitwind(FALSE, 1) == FALSE)
  348. X            return(FALSE);
  349. X
  350. X    /* and get a buffer for it */
  351. X    bp = bfind("Binding list", TRUE, 0);
  352. X    if (bp == NULL || bclear(bp) == FALSE) {
  353. X        mlwrite("Can not display binding list");
  354. X        return(FALSE);
  355. X    }
  356. X
  357. X    /* let us know this is in progress */
  358. X    mlwrite("[Building buffer list]");
  359. X
  360. X    /* disconect the current buffer */
  361. X        if (--curbp->b_nwnd == 0) {             /* Last use.            */
  362. X                curbp->b_dotp  = curwp->w_dotp;
  363. X                curbp->b_doto  = curwp->w_doto;
  364. X                curbp->b_markp = curwp->w_markp;
  365. X                curbp->b_marko = curwp->w_marko;
  366. X        }
  367. X
  368. X    /* connect the current window to this buffer */
  369. X    curbp = bp;    /* make this buffer current in current window */
  370. X    bp->b_mode = 0;        /* no modes active in binding list */
  371. X    bp->b_nwnd++;        /* mark us as more in use */
  372. X    wp = curwp;
  373. X    wp->w_bufp = bp;
  374. X    wp->w_linep = bp->b_linep;
  375. X    wp->w_flag = WFHARD|WFFORCE|WFHARD;
  376. X    wp->w_dotp = bp->b_dotp;
  377. X    wp->w_doto = bp->b_doto;
  378. X    wp->w_markp = NULL;
  379. X    wp->w_marko = 0;
  380. X
  381. X    /* build the contents of this window, inserting it line by line */
  382. X    nptr = &names[0];
  383. X    while (nptr->n_func != NULL) {
  384. X
  385. X        /* add in the command name */
  386. X        strcpy(outseq, nptr->n_name);
  387. X        cpos = strlen(outseq);
  388. X        
  389. X        /* search down any keys bound to this */
  390. X        ktp = &keytab[0];
  391. X        while (ktp->k_fp != NULL) {
  392. X            if (ktp->k_fp == nptr->n_func) {
  393. X                /* padd out some spaces */
  394. X                while (cpos < 25)
  395. X                    outseq[cpos++] = ' ';
  396. X
  397. X                /* add in the command sequence */
  398. X                cmdstr(ktp->k_code, &outseq[cpos]);
  399. X                while (outseq[cpos] != 0)
  400. X                    ++cpos;
  401. X
  402. X                /* and add it as a line into the buffer */
  403. X                strp = &outseq[0];
  404. X                while (*strp != 0)
  405. X                    linsert(1, *strp++);
  406. X                lnewline();
  407. X
  408. X                cpos = 0;    /* and clear the line */
  409. X            }
  410. X            ++ktp;
  411. X        }
  412. X
  413. X        /* if no key was bound, we need to dump it anyway */
  414. X        if (cpos > 0) {
  415. X            outseq[cpos] = 0;
  416. X            strp = &outseq[0];
  417. X            while (*strp != 0)
  418. X                linsert(1, *strp++);
  419. X            lnewline();
  420. X        }
  421. X
  422. X        /* and on to the next name */
  423. X        ++nptr;
  424. X    }
  425. X
  426. X    curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */
  427. X    curbp->b_flag &= ~BFCHG;    /* don't flag this as a change */
  428. X    wp->w_dotp = lforw(bp->b_linep);/* back to the begining */
  429. X    wp->w_doto = 0;
  430. X    wp = wheadp;            /* and update ALL mode lines */
  431. X    while (wp != NULL) {
  432. X        wp->w_flag |= WFMODE;
  433. X        wp = wp->w_wndp;
  434. X    }
  435. X    mlwrite("");    /* clear the mode line */
  436. X    return(TRUE);
  437. X}
  438. X
  439. X/*    execcmd:    Execute a command line command to be typed in
  440. X            by the user                    */
  441. X
  442. Xexeccmd(f, n)
  443. X
  444. Xint f, n;    /* default Flag and Numeric argument */
  445. X
  446. X{
  447. X    register int status;        /* status return */
  448. X    char cmdstr[NSTRING];        /* string holding command to execute */
  449. X
  450. X    /* get the line wanted */
  451. X    if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE)
  452. X        return(status);
  453. X
  454. X    return(docmd(cmdstr));
  455. X}
  456. X
  457. X/*    docmd:    take a passed string as a command line and translate
  458. X        it to be executed as a command. This function will be
  459. X        used by execute-command-line and by all source and
  460. X        startup files.
  461. X
  462. X    format of the command line is:
  463. X
  464. X        {# arg} <command-name> {<argument string(s)>}
  465. X*/
  466. X
  467. Xdocmd(cline)
  468. X
  469. Xchar *cline;    /* command line to execute */
  470. X
  471. X{
  472. X    register char *cp;    /* pointer to current position in command */
  473. X    register char *tp;    /* pointer to current position in token */
  474. X    register int f;        /* default argument flag */
  475. X    register int n;        /* numeric repeat value */
  476. X    register int sign;    /* sign of numeric argument */
  477. X    register int (*fnc)();    /* function to execute */
  478. X    register int status;    /* return status of function */
  479. X    register int oldcle;    /* old contents of clexec flag */
  480. X    char token[NSTRING];    /* next token off of command line */
  481. X    int (*fncmatch())();
  482. X    char *gettok();
  483. X
  484. X    /* first set up the default command values */
  485. X    f = FALSE;
  486. X    n = 1;
  487. X
  488. X    cp = cline;        /* start at the begining of the line */
  489. X    cp = gettok(cp, token);    /* and grab the first token */
  490. X
  491. X    /* check for and process numeric leadin argument */
  492. X    if ((token[0] >= '0' && token[0] <= '9') || token[0] == '-') {
  493. X        f = TRUE;
  494. X        n = 0;
  495. X        tp = &token[0];
  496. X
  497. X        /* check for a sign! */
  498. X        sign = 1;
  499. X        if (*tp == '-') {
  500. X            ++tp;
  501. X            sign = -1;
  502. X        }
  503. X
  504. X        /* calc up the digits in the token string */
  505. X        while(*tp) {
  506. X            if (*tp >= '0' && *tp <= '9')
  507. X                n = n * 10 + *tp - '0';
  508. X            ++tp;
  509. X        }
  510. X        n *= sign;    /* adjust for the sign */
  511. X
  512. X        /* and now get the command to execute */
  513. X        cp = gettok(cp, token);        /* grab the next token */
  514. X    }
  515. X
  516. X    /* and match the token to see if it exists */
  517. X    if ((fnc = fncmatch(token)) == NULL) {
  518. X        mlwrite("[No such Function]");
  519. X        return(FALSE);
  520. X    }
  521. X    
  522. X    /* save the arguments and go execute the command */
  523. X    strcpy(sarg, cp);        /* save the rest */
  524. X    oldcle = clexec;        /* save old clexec flag */
  525. X    clexec = TRUE;            /* in cline execution */
  526. X    status = (*fnc)(f, n);        /* call the function */
  527. X    clexec = oldcle;        /* restore clexec flag */
  528. X    return(status);
  529. X}
  530. X
  531. X/* gettok:    chop a token off a string
  532. X        return a pointer past the token
  533. X*/
  534. X
  535. Xchar *gettok(src, tok)
  536. X
  537. Xchar *src, *tok;    /* source string, destination token */
  538. X
  539. X{
  540. X    /* first scan past any whitespace in the source string */
  541. X    while (*src == ' ' || *src == '\t')
  542. X        ++src;
  543. X
  544. X    /* if quoted, go till next quote */
  545. X    if (*src == '"') {
  546. X        ++src;        /* past the quote */
  547. X        while (*src != 0 && *src != '"')
  548. X            *tok++ = *src++;
  549. X        ++src;        /* past the last quote */
  550. X        *tok = 0;    /* terminate token and return */
  551. X        return(src);
  552. X    }
  553. X
  554. X    /* copy until we find the end or whitespace */
  555. X    while (*src != 0 && *src != ' ' && *src != '\t')
  556. X        *tok++ = *src++;
  557. X
  558. X    /* terminate tok and return */
  559. X    *tok = 0;
  560. X    return(src);
  561. X}
  562. X
  563. X/* nxtarg:    grab the next token out of sarg, return it, and
  564. X        chop it of sarg                    */
  565. X
  566. Xnxtarg(tok)
  567. X
  568. Xchar *tok;    /* buffer to put token into */
  569. X
  570. X{
  571. X    char *newsarg;    /* pointer to new begining of sarg */
  572. X    char *gettok();
  573. X
  574. X    newsarg = gettok(sarg, tok);    /* grab the token */
  575. X    strcpy(sarg, newsarg);        /* and chop it of sarg */
  576. X    return(TRUE);
  577. X}
  578. X
  579. Xgetckey()    /* get a command key sequence from the keyboard    */
  580. X
  581. X{
  582. X    register int c;        /* character fetched */
  583. X    register char *tp;    /* pointer into the token */
  584. X    char tok[NSTRING];    /* command incoming */
  585. X
  586. X    /* check to see if we are executing a command line */
  587. X    if (clexec) {
  588. X        nxtarg(tok);    /* get the next token */
  589. X
  590. X        /* parse it up */
  591. X        tp = &tok[0];
  592. X        c = 0;
  593. X
  594. X        /* first, the META prefix */
  595. X        if (*tp == 'M' && *(tp+1) == '-') {
  596. X            c = META;
  597. X            tp += 2;
  598. X        }
  599. X
  600. X        /* next the function prefix */
  601. X        if (*tp == 'F' && *(tp+1) == 'N') {
  602. X            c |= SPEC;
  603. X            tp += 2;
  604. X        }
  605. X
  606. X        /* control-x as well... */
  607. X        if (*tp == '^' && *(tp+1) == 'X') {
  608. X            c |= CTLX;
  609. X            tp += 2;
  610. X        }
  611. X
  612. X        /* a control char? */
  613. X        if (*tp == '^' & *(tp+1) != 0) {
  614. X            c |= CTRL;
  615. X            ++tp;
  616. X        }
  617. X
  618. X        /* make sure we are not lower case */
  619. X        if (c >= 'a' && c <= 'z')
  620. X            c -= 32;
  621. X
  622. X        /* the final sequence... */
  623. X        c |= *tp;
  624. X
  625. X        return(c);
  626. X    }
  627. X
  628. X    /* or the normal way */
  629. X    c = getkey();            /* get a command sequence */
  630. X    if (c == (CTRL|'X'))        /* get control-x sequence */
  631. X        c = CTLX | getctl();
  632. X    return(c);
  633. X}
  634. X
  635. X/*    execbuf:    Execute the contents of a named buffer    */
  636. X
  637. Xexecbuf(f, n)
  638. X
  639. Xint f, n;    /* default flag and numeric arg */
  640. X
  641. X{
  642. X        register BUFFER *bp;        /* ptr to buffer to execute */
  643. X        register int status;        /* status return */
  644. X        char bufn[NBUFN];        /* name of buffer to execute */
  645. X
  646. X    /* find out what buffer the user wants to execute */
  647. X        if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE)
  648. X                return(status);
  649. X
  650. X    /* find the pointer to that buffer */
  651. X        if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  652. X                return(FALSE);
  653. X
  654. X    /* and now execute it as asked */
  655. X    while (n-- > 0)
  656. X        if ((status = dobuf(bp)) != TRUE)
  657. X            return(status);
  658. X    return(TRUE);
  659. X}
  660. X
  661. X/*    dobuf:    execute the contents of the buffer pointed to
  662. X        by the passed BP                */
  663. X
  664. Xdobuf(bp)
  665. X
  666. XBUFFER *bp;    /* buffer to execute */
  667. X
  668. X{
  669. X        register int status;        /* status return */
  670. X    register LINE *lp;        /* pointer to line to execute */
  671. X    register LINE *hlp;        /* pointer to line header */
  672. X    register int linlen;        /* length of line to execute */
  673. X    register WINDOW *wp;        /* ptr to windows to scan */
  674. X    char eline[NSTRING];        /* text of line to execute */
  675. X
  676. X    /* starting at the beginning of the buffer */
  677. X    hlp = bp->b_linep;
  678. X    lp = hlp->l_fp;
  679. X    while (lp != hlp) {
  680. X        /* calculate the line length and make a local copy */
  681. X        linlen = lp->l_used;
  682. X        if (linlen > NSTRING - 1)
  683. X            linlen = NSTRING - 1;
  684. X        strncpy(eline, lp->l_text, linlen);
  685. X        eline[linlen] = 0;    /* make sure it ends */
  686. X
  687. X        /* if it is not a comment, execute it */
  688. X        if (eline[0] != ';' && eline[0] != 0) {
  689. X            status = docmd(eline);
  690. X            if (status != TRUE) {    /* a command error */
  691. X                /* look if buffer is showing */
  692. X                wp = wheadp;
  693. X                while (wp != NULL) {
  694. X                    if (wp->w_bufp == bp) {
  695. X                        /* and point it */
  696. X                        wp->w_dotp = lp;
  697. X                        wp->w_doto = 0;
  698. X                        wp->w_flag |= WFHARD;
  699. X                    }
  700. X                    wp = wp->w_wndp;
  701. X                }
  702. X                /* in any case set the buffer . */
  703. X                bp->b_dotp = lp;
  704. X                bp->b_doto = 0;
  705. X                return(status);
  706. X            }
  707. X        }
  708. X        lp = lp->l_fp;        /* on to the next line */
  709. X    }
  710. X        return(TRUE);
  711. X}
  712. X
  713. Xexecfile(f, n)    /* execute a series of commands in a file
  714. X*/
  715. X
  716. Xint f, n;    /* default flag and numeric arg to pass on to file */
  717. X
  718. X{
  719. X    register int status;    /* return status of name query */
  720. X    char *fname[NSTRING];    /* name of file to execute */
  721. X
  722. X    if ((status = mlreply("File to execute: ", fname, NSTRING -1)) != TRUE)
  723. X        return(status);
  724. X
  725. X    /* otherwise, execute it */
  726. X    while (n-- > 0)
  727. X        if ((status=dofile(fname)) != TRUE)
  728. X            return(status);
  729. X
  730. X    return(TRUE);
  731. X}
  732. X
  733. X/*    dofile:    yank a file into a buffer and execute it
  734. X        if there are no errors, delete the buffer on exit */
  735. X
  736. Xdofile(fname)
  737. X
  738. Xchar *fname;    /* file name to execute */
  739. X
  740. X{
  741. X    register BUFFER *bp;    /* buffer to place file to exeute */
  742. X    register BUFFER *cb;    /* temp to hold current buf while we read */
  743. X    register int status;    /* results of various calls */
  744. X    char bname[NBUFN];    /* name of buffer */
  745. X
  746. X    makename(bname, fname);        /* derive the name of the buffer */
  747. X    if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */
  748. X        return(FALSE);
  749. X
  750. X    bp->b_mode = MDVIEW;    /* mark the buffer as read only */
  751. X    cb = curbp;        /* save the old buffer */
  752. X    curbp = bp;        /* make this one current */
  753. X    /* and try to read in the file to execute */
  754. X    if ((status = readin(fname, FALSE)) != TRUE) {
  755. X        curbp = cb;    /* restore the current buffer */
  756. X        return(status);
  757. X    }
  758. X
  759. X    /* go execute it! */
  760. X    curbp = cb;        /* restore the current buffer */
  761. X    if ((status = dobuf(bp)) != TRUE)
  762. X        return(status);
  763. X
  764. X    /* if not displayed, remove the now unneeded buffer and exit */
  765. X    if (bp->b_nwnd == 0)
  766. X        zotbuf(bp);
  767. X    return(TRUE);
  768. X}
  769. X
  770. X
  771. X/* execute the startup file */
  772. X
  773. Xstartup()
  774. X
  775. X{
  776. X    register int status;    /* status of I/O operations */
  777. X    register int i;        /* index into help file names */
  778. X    char fname[NSTRING];    /* buffer to construct file name in */
  779. X
  780. X#if    (MSDOS & LATTICE) | V7
  781. X    char *homedir;        /* pointer to your home directory */
  782. X    char *getenv();
  783. X    
  784. X    /* get the HOME from the environment */
  785. X    if ((homedir = getenv("HOME")) != NULL) {
  786. X        /* build the file name */
  787. X        strcpy(fname, homedir);
  788. X        strcat(fname, "/");
  789. X        strcat(fname, pathname[0]);
  790. X
  791. X        /* and test it */
  792. X        status = ffropen(fname);
  793. X        if (status == FIOSUC) {
  794. X            ffclose();
  795. X            return(dofile(fname));
  796. X        }
  797. X    }
  798. X#endif
  799. X
  800. X    /* search through the list of startup files */
  801. X    for (i=2; i < NPNAMES; i++) {
  802. X        strcpy(fname, pathname[i]);
  803. X        strcat(fname, pathname[0]);
  804. X        status = ffropen(fname);
  805. X        if (status == FIOSUC)
  806. X            break;
  807. X    }
  808. X
  809. X    /* if it isn't around, don't sweat it */
  810. X    if (status == FIOFNF)
  811. X        return(TRUE);
  812. X
  813. X    ffclose();    /* close the file to prepare for to read it in */
  814. X
  815. X    return(dofile(fname));
  816. X}
  817. X
  818. *-*-END-of-bind.c-*-*
  819. echo x - buffer.c
  820. sed 's/^X//' >buffer.c <<'*-*-END-of-buffer.c-*-*'
  821. X/*
  822. X * Buffer management.
  823. X * Some of the functions are internal,
  824. X * and some are actually attached to user
  825. X * keys. Like everyone else, they set hints
  826. X * for the display system.
  827. X */
  828. X#include        <stdio.h>
  829. X#include    "estruct.h"
  830. X#include        "edef.h"
  831. X
  832. X/*
  833. X * Attach a buffer to a window. The
  834. X * values of dot and mark come from the buffer
  835. X * if the use count is 0. Otherwise, they come
  836. X * from some other window.
  837. X */
  838. Xusebuffer(f, n)
  839. X{
  840. X        register BUFFER *bp;
  841. X        register int    s;
  842. X        char            bufn[NBUFN];
  843. X
  844. X        if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
  845. X                return (s);
  846. X        if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  847. X                return (FALSE);
  848. X    return(swbuffer(bp));
  849. X}
  850. X
  851. Xnextbuffer(f, n)    /* switch to the next buffer in the buffer list */
  852. X
  853. X{
  854. X        register BUFFER *bp;
  855. X        char            bufn[NBUFN];
  856. X
  857. X    bp = curbp->b_bufp;
  858. X    /* cycle through the buffers to find an eligable one */
  859. X    while (bp == NULL | bp->b_flag & BFTEMP) {
  860. X        if (bp == NULL)
  861. X            bp = bheadp;
  862. X        else
  863. X            bp = bp->b_bufp;
  864. X    }
  865. X    return(swbuffer(bp));
  866. X}
  867. X
  868. Xswbuffer(bp)    /* make buffer BP current */
  869. X
  870. XBUFFER *bp;
  871. X
  872. X{
  873. X        register WINDOW *wp;
  874. X
  875. X        if (--curbp->b_nwnd == 0) {             /* Last use.            */
  876. X                curbp->b_dotp  = curwp->w_dotp;
  877. X                curbp->b_doto  = curwp->w_doto;
  878. X                curbp->b_markp = curwp->w_markp;
  879. X                curbp->b_marko = curwp->w_marko;
  880. X        }
  881. X        curbp = bp;                             /* Switch.              */
  882. X    if (curbp->b_active != TRUE) {        /* buffer not active yet*/
  883. X        /* read it in and activate it */
  884. X        readin(curbp->b_fname, TRUE);
  885. X        curbp->b_dotp = lforw(curbp->b_linep);
  886. X        curbp->b_doto = 0;
  887. X        curbp->b_active = TRUE;
  888. X    }
  889. X        curwp->w_bufp  = bp;
  890. X        curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  891. X        curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  892. X        if (bp->b_nwnd++ == 0) {                /* First use.           */
  893. X                curwp->w_dotp  = bp->b_dotp;
  894. X                curwp->w_doto  = bp->b_doto;
  895. X                curwp->w_markp = bp->b_markp;
  896. X                curwp->w_marko = bp->b_marko;
  897. X                return (TRUE);
  898. X        }
  899. X        wp = wheadp;                            /* Look for old.        */
  900. X        while (wp != NULL) {
  901. X                if (wp!=curwp && wp->w_bufp==bp) {
  902. X                        curwp->w_dotp  = wp->w_dotp;
  903. X                        curwp->w_doto  = wp->w_doto;
  904. X                        curwp->w_markp = wp->w_markp;
  905. X                        curwp->w_marko = wp->w_marko;
  906. X                        break;
  907. X                }
  908. X                wp = wp->w_wndp;
  909. X        }
  910. X        return (TRUE);
  911. X}
  912. X
  913. X/*
  914. X * Dispose of a buffer, by name.
  915. X * Ask for the name. Look it up (don't get too
  916. X * upset if it isn't there at all!). Get quite upset
  917. X * if the buffer is being displayed. Clear the buffer (ask
  918. X * if the buffer has been changed). Then free the header
  919. X * line and the buffer header. Bound to "C-X K".
  920. X */
  921. Xkillbuffer(f, n)
  922. X
  923. X{
  924. X    register BUFFER *bp;
  925. X        register int    s;
  926. X        char bufn[NBUFN];
  927. X
  928. X        if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  929. X                return(s);
  930. X        if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
  931. X                return (TRUE);
  932. X    return(zotbuf(bp));
  933. X}
  934. X
  935. Xzotbuf(bp)    /* kill the buffer pointed to by bp */
  936. X
  937. Xregister BUFFER *bp;
  938. X
  939. X{
  940. X        register BUFFER *bp1;
  941. X        register BUFFER *bp2;
  942. X        register int    s;
  943. X
  944. X        if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  945. X                mlwrite("Buffer is being displayed");
  946. X                return (FALSE);
  947. X        }
  948. X        if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  949. X                return (s);
  950. X        free((char *) bp->b_linep);             /* Release header line. */
  951. X        bp1 = NULL;                             /* Find the header.     */
  952. X        bp2 = bheadp;
  953. X        while (bp2 != bp) {
  954. X                bp1 = bp2;
  955. X                bp2 = bp2->b_bufp;
  956. X        }
  957. X        bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  958. X        if (bp1 == NULL)                        /* Unlink it.           */
  959. X                bheadp = bp2;
  960. X        else
  961. X                bp1->b_bufp = bp2;
  962. X        free((char *) bp);                      /* Release buffer block */
  963. X        return (TRUE);
  964. X}
  965. X
  966. Xnamebuffer(f,n)        /*    Rename the current buffer    */
  967. X
  968. Xint f, n;        /* default Flag & Numeric arg */
  969. X
  970. X{
  971. X    register BUFFER *bp;    /* pointer to scan through all buffers */
  972. X    char bufn[NBUFN];    /* buffer to hold buffer name */
  973. X
  974. X    /* prompt for and get the new buffer name */
  975. Xask:    if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
  976. X        return(FALSE);
  977. X
  978. X    /* and check for duplicates */
  979. X    bp = bheadp;
  980. X    while (bp != NULL) {
  981. X        if (bp != curbp) {
  982. X            /* if the names the same */
  983. X            if (strcmp(bufn, bp->b_bname) == 0)
  984. X                goto ask;  /* try again */
  985. X        }
  986. X        bp = bp->b_bufp;    /* onward */
  987. X    }
  988. X
  989. X    strcpy(curbp->b_bname, bufn);    /* copy buffer name to structure */
  990. X    curwp->w_flag |= WFMODE;    /* make mode line replot */
  991. X    mlerase();
  992. X}
  993. X
  994. X/*
  995. X * List all of the active
  996. X * buffers. First update the special
  997. X * buffer that holds the list. Next make
  998. X * sure at least 1 window is displaying the
  999. X * buffer list, splitting the screen if this
  1000. X * is what it takes. Lastly, repaint all of
  1001. X * the windows that are displaying the
  1002. X * list. Bound to "C-X C-B".
  1003. X */
  1004. Xlistbuffers(f, n)
  1005. X{
  1006. X        register WINDOW *wp;
  1007. X        register BUFFER *bp;
  1008. X        register int    s;
  1009. X
  1010. X        if ((s=makelist()) != TRUE)
  1011. X                return (s);
  1012. X        if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  1013. X                if ((wp=wpopup()) == NULL)
  1014. X                        return (FALSE);
  1015. X                bp = wp->w_bufp;
  1016. X                if (--bp->b_nwnd == 0) {
  1017. X                        bp->b_dotp  = wp->w_dotp;
  1018. X                        bp->b_doto  = wp->w_doto;
  1019. X                        bp->b_markp = wp->w_markp;
  1020. X                        bp->b_marko = wp->w_marko;
  1021. X                }
  1022. X                wp->w_bufp  = blistp;
  1023. X                ++blistp->b_nwnd;
  1024. X        }
  1025. X        wp = wheadp;
  1026. X        while (wp != NULL) {
  1027. X                if (wp->w_bufp == blistp) {
  1028. X                        wp->w_linep = lforw(blistp->b_linep);
  1029. X                        wp->w_dotp  = lforw(blistp->b_linep);
  1030. X                        wp->w_doto  = 0;
  1031. X                        wp->w_markp = NULL;
  1032. X                        wp->w_marko = 0;
  1033. X                        wp->w_flag |= WFMODE|WFHARD;
  1034. X                }
  1035. X                wp = wp->w_wndp;
  1036. X        }
  1037. X        return (TRUE);
  1038. X}
  1039. X
  1040. X/*
  1041. X * This routine rebuilds the
  1042. X * text in the special secret buffer
  1043. X * that holds the buffer list. It is called
  1044. X * by the list buffers command. Return TRUE
  1045. X * if everything works. Return FALSE if there
  1046. X * is an error (if there is no memory).
  1047. X */
  1048. Xmakelist()
  1049. X{
  1050. X        register char   *cp1;
  1051. X        register char   *cp2;
  1052. X        register int    c;
  1053. X        register BUFFER *bp;
  1054. X        register LINE   *lp;
  1055. X        register int    nbytes;
  1056. X        register int    s;
  1057. X    register int    i;
  1058. X        register int    type;
  1059. X        char            b[6+1];
  1060. X        char            line[128];
  1061. X
  1062. X        blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  1063. X        if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  1064. X                return (s);
  1065. X        strcpy(blistp->b_fname, "");
  1066. X        if (addline("AC MODES    Size Buffer         File") == FALSE
  1067. X        ||  addline("-- -----    ---- ------         ----") == FALSE)
  1068. X                return (FALSE);
  1069. X        bp = bheadp;                            /* For all buffers      */
  1070. X
  1071. X    /* build line to report global mode settings */
  1072. X    cp1 = &line[0];
  1073. X    *cp1++ = ' ';
  1074. X    *cp1++ = ' ';
  1075. X    *cp1++ = ' ';
  1076. X
  1077. X    /* output the mode codes */
  1078. X    for (i = 0; i < NUMMODES; i++)
  1079. X        if (gmode & (1 << i))
  1080. X            *cp1++ = modecode[i];
  1081. X        else
  1082. X            *cp1++ = '.';
  1083. X    strcpy(cp1, "        Global Modes");
  1084. X    if (addline(line) == FALSE)
  1085. X        return(FALSE);
  1086. X
  1087. X    /* output the list of buffers */
  1088. X        while (bp != NULL) {
  1089. X                if ((bp->b_flag&BFTEMP) != 0) { /* Skip magic ones.     */
  1090. X                        bp = bp->b_bufp;
  1091. X                        continue;
  1092. X                }
  1093. X                cp1 = &line[0];                 /* Start at left edge   */
  1094. X
  1095. X        /* output status of ACTIVE flag (has the file been read in? */
  1096. X                if (bp->b_active == TRUE)    /* "@" if activated       */
  1097. X                        *cp1++ = '@';
  1098. X                else
  1099. X                        *cp1++ = ' ';
  1100. X
  1101. X        /* output status of changed flag */
  1102. X                if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  1103. X                        *cp1++ = '*';
  1104. X                else
  1105. X                        *cp1++ = ' ';
  1106. X                *cp1++ = ' ';                   /* Gap.                 */
  1107. X
  1108. X        /* output the mode codes */
  1109. X        for (i = 0; i < NUMMODES; i++) {
  1110. X            if (bp->b_mode & (1 << i))
  1111. X                *cp1++ = modecode[i];
  1112. X            else
  1113. X                *cp1++ = '.';
  1114. X        }
  1115. X                *cp1++ = ' ';                   /* Gap.                 */
  1116. X                nbytes = 0;                     /* Count bytes in buf.  */
  1117. X                lp = lforw(bp->b_linep);
  1118. X                while (lp != bp->b_linep) {
  1119. X                        nbytes += llength(lp)+1;
  1120. X                        lp = lforw(lp);
  1121. X                }
  1122. X                itoa(b, 6, nbytes);             /* 6 digit buffer size. */
  1123. X                cp2 = &b[0];
  1124. X                while ((c = *cp2++) != 0)
  1125. X                        *cp1++ = c;
  1126. X                *cp1++ = ' ';                   /* Gap.                 */
  1127. X                cp2 = &bp->b_bname[0];          /* Buffer name          */
  1128. X                while ((c = *cp2++) != 0)
  1129. X                        *cp1++ = c;
  1130. X                cp2 = &bp->b_fname[0];          /* File name            */
  1131. X                if (*cp2 != 0) {
  1132. X                        while (cp1 < &line[2+1+5+1+6+1+NBUFN])
  1133. X                                *cp1++ = ' ';
  1134. X                        while ((c = *cp2++) != 0) {
  1135. X                                if (cp1 < &line[128-1])
  1136. X                                        *cp1++ = c;
  1137. X                        }
  1138. X                }
  1139. X                *cp1 = 0;                       /* Add to the buffer.   */
  1140. X                if (addline(line) == FALSE)
  1141. X                        return (FALSE);
  1142. X                bp = bp->b_bufp;
  1143. X        }
  1144. X        return (TRUE);                          /* All done             */
  1145. X}
  1146. X
  1147. Xitoa(buf, width, num)
  1148. Xregister char   buf[];
  1149. Xregister int    width;
  1150. Xregister int    num;
  1151. X{
  1152. X        buf[width] = 0;                         /* End of string.       */
  1153. X        while (num >= 10) {                     /* Conditional digits.  */
  1154. X                buf[--width] = (num%10) + '0';
  1155. X                num /= 10;
  1156. X        }
  1157. X        buf[--width] = num + '0';               /* Always 1 digit.      */
  1158. X        while (width != 0)                      /* Pad with blanks.     */
  1159. X                buf[--width] = ' ';
  1160. X}
  1161. X
  1162. X/*
  1163. X * The argument "text" points to
  1164. X * a string. Append this line to the
  1165. X * buffer list buffer. Handcraft the EOL
  1166. X * on the end. Return TRUE if it worked and
  1167. X * FALSE if you ran out of room.
  1168. X */
  1169. Xaddline(text)
  1170. Xchar    *text;
  1171. X{
  1172. X        register LINE   *lp;
  1173. X        register int    i;
  1174. X        register int    ntext;
  1175. X
  1176. X        ntext = strlen(text);
  1177. X        if ((lp=lalloc(ntext)) == NULL)
  1178. X                return (FALSE);
  1179. X        for (i=0; i<ntext; ++i)
  1180. X                lputc(lp, i, text[i]);
  1181. X        blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  1182. X        lp->l_bp = blistp->b_linep->l_bp;
  1183. X        blistp->b_linep->l_bp = lp;
  1184. X        lp->l_fp = blistp->b_linep;
  1185. X        if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  1186. X                blistp->b_dotp = lp;            /* move it to new line  */
  1187. X        return (TRUE);
  1188. X}
  1189. X
  1190. X/*
  1191. X * Look through the list of
  1192. X * buffers. Return TRUE if there
  1193. X * are any changed buffers. Buffers
  1194. X * that hold magic internal stuff are
  1195. X * not considered; who cares if the
  1196. X * list of buffer names is hacked.
  1197. X * Return FALSE if no buffers
  1198. X * have been changed.
  1199. X */
  1200. Xanycb()
  1201. X{
  1202. X        register BUFFER *bp;
  1203. X
  1204. X        bp = bheadp;
  1205. X        while (bp != NULL) {
  1206. X                if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0)
  1207. X                        return (TRUE);
  1208. X                bp = bp->b_bufp;
  1209. X        }
  1210. X        return (FALSE);
  1211. X}
  1212. X
  1213. X/*
  1214. X * Find a buffer, by name. Return a pointer
  1215. X * to the BUFFER structure associated with it. If
  1216. X * the named buffer is found, but is a TEMP buffer (like
  1217. X * the buffer list) conplain. If the buffer is not found
  1218. X * and the "cflag" is TRUE, create it. The "bflag" is
  1219. X * the settings for the flags in in buffer.
  1220. X */
  1221. XBUFFER  *
  1222. Xbfind(bname, cflag, bflag)
  1223. Xregister char   *bname;
  1224. X{
  1225. X        register BUFFER *bp;
  1226. X    register BUFFER *sb;    /* buffer to insert after */
  1227. X        register LINE   *lp;
  1228. X    char *malloc();
  1229. X
  1230. X        bp = bheadp;
  1231. X        while (bp != NULL) {
  1232. X                if (strcmp(bname, bp->b_bname) == 0) {
  1233. X                        if ((bp->b_flag&BFTEMP) != 0) {
  1234. X                                mlwrite("Cannot select builtin buffer");
  1235. X                                return (NULL);
  1236. X                        }
  1237. X                        return (bp);
  1238. X                }
  1239. X                bp = bp->b_bufp;
  1240. X        }
  1241. X        if (cflag != FALSE) {
  1242. X                if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  1243. X                        return (NULL);
  1244. X                if ((lp=lalloc(0)) == NULL) {
  1245. X                        free((char *) bp);
  1246. X                        return (NULL);
  1247. X                }
  1248. X        /* find the place in the list to insert this buffer */
  1249. X        if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
  1250. X            /* insert at the begining */
  1251. X                    bp->b_bufp = bheadp;
  1252. X                    bheadp = bp;
  1253. X            } else {
  1254. X            sb = bheadp;
  1255. X            while (sb->b_bufp != NULL) {
  1256. X                if (strcmp(sb->b_bufp->b_bname, bname) > 0)
  1257. X                    break;
  1258. X                sb = sb->b_bufp;
  1259. X            }
  1260. X
  1261. X            /* and insert it */
  1262. X                   bp->b_bufp = sb->b_bufp;
  1263. X                sb->b_bufp = bp;
  1264. X               }
  1265. X
  1266. X        /* and set up the other buffer fields */
  1267. X        bp->b_active = TRUE;
  1268. X                bp->b_dotp  = lp;
  1269. X                bp->b_doto  = 0;
  1270. X                bp->b_markp = NULL;
  1271. X                bp->b_marko = 0;
  1272. X                bp->b_flag  = bflag;
  1273. X        bp->b_mode  = gmode;
  1274. X                bp->b_nwnd  = 0;
  1275. X                bp->b_linep = lp;
  1276. X                strcpy(bp->b_fname, "");
  1277. X                strcpy(bp->b_bname, bname);
  1278. X                lp->l_fp = lp;
  1279. X                lp->l_bp = lp;
  1280. X        }
  1281. X        return (bp);
  1282. X}
  1283. X
  1284. X/*
  1285. X * This routine blows away all of the text
  1286. X * in a buffer. If the buffer is marked as changed
  1287. X * then we ask if it is ok to blow it away; this is
  1288. X * to save the user the grief of losing text. The
  1289. X * window chain is nearly always wrong if this gets
  1290. X * called; the caller must arrange for the updates
  1291. X * that are required. Return TRUE if everything
  1292. X * looks good.
  1293. X */
  1294. Xbclear(bp)
  1295. Xregister BUFFER *bp;
  1296. X{
  1297. X        register LINE   *lp;
  1298. X        register int    s;
  1299. X
  1300. X        if ((bp->b_flag&BFTEMP) == 0            /* Not scratch buffer.  */
  1301. X        && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  1302. X        && (s=mlyesno("Discard changes")) != TRUE)
  1303. X                return (s);
  1304. X        bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  1305. X        while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  1306. X                lfree(lp);
  1307. X        bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  1308. X        bp->b_doto  = 0;
  1309. X        bp->b_markp = NULL;                     /* Invalidate "mark"    */
  1310. X        bp->b_marko = 0;
  1311. X        return (TRUE);
  1312. X}
  1313. *-*-END-of-buffer.c-*-*
  1314. echo x - fileio.c
  1315. sed 's/^X//' >fileio.c <<'*-*-END-of-fileio.c-*-*'
  1316. X/*
  1317. X * The routines in this file read and write ASCII files from the disk. All of
  1318. X * the knowledge about files are here. A better message writing scheme should
  1319. X * be used.
  1320. X */
  1321. X#include        <stdio.h>
  1322. X#include    "estruct.h"
  1323. X#include        "edef.h"
  1324. X
  1325. XFILE    *ffp;                           /* File pointer, all functions. */
  1326. X
  1327. X/*
  1328. X * Open a file for reading.
  1329. X */
  1330. Xffropen(fn)
  1331. Xchar    *fn;
  1332. X{
  1333. X        if ((ffp=fopen(fn, "r")) == NULL)
  1334. X                return (FIOFNF);
  1335. X        return (FIOSUC);
  1336. X}
  1337. X
  1338. X/*
  1339. X * Open a file for writing. Return TRUE if all is well, and FALSE on error
  1340. X * (cannot create).
  1341. X */
  1342. Xffwopen(fn)
  1343. Xchar    *fn;
  1344. X{
  1345. X#if     VMS
  1346. X        register int    fd;
  1347. X
  1348. X        if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0
  1349. X        || (ffp=fdopen(fd, "w")) == NULL) {
  1350. X#else
  1351. X        if ((ffp=fopen(fn, "w")) == NULL) {
  1352. X#endif
  1353. X                mlwrite("Cannot open file for writing");
  1354. X                return (FIOERR);
  1355. X        }
  1356. X        return (FIOSUC);
  1357. X}
  1358. X
  1359. X/*
  1360. X * Close a file. Should look at the status in all systems.
  1361. X */
  1362. Xffclose()
  1363. X{
  1364. X#if    MSDOS
  1365. X    fputc(26, ffp);        /* add a ^Z at the end of the file */
  1366. X#endif
  1367. X    
  1368. X#if     V7 | (MSDOS & LATTICE)
  1369. X        if (fclose(ffp) != FALSE) {
  1370. X                mlwrite("Error closing file");
  1371. X                return(FIOERR);
  1372. X        }
  1373. X        return(FIOSUC);
  1374. X#else
  1375. X        fclose(ffp);
  1376. X        return (FIOSUC);
  1377. X#endif
  1378. X}
  1379. X
  1380. X/*
  1381. X * Write a line to the already opened file. The "buf" points to the buffer,
  1382. X * and the "nbuf" is its length, less the free newline. Return the status.
  1383. X * Check only at the newline.
  1384. X */
  1385. Xffputline(buf, nbuf)
  1386. Xchar    buf[];
  1387. X{
  1388. X        register int    i;
  1389. X
  1390. X        for (i = 0; i < nbuf; ++i)
  1391. X                fputc(buf[i]&0xFF, ffp);
  1392. X
  1393. X        fputc('\n', ffp);
  1394. X
  1395. X        if (ferror(ffp)) {
  1396. X                mlwrite("Write I/O error");
  1397. X                return (FIOERR);
  1398. X        }
  1399. X
  1400. X        return (FIOSUC);
  1401. X}
  1402. X
  1403. X/*
  1404. X * Read a line from a file, and store the bytes in the supplied buffer. The
  1405. X * "nbuf" is the length of the buffer. Complain about long lines and lines
  1406. X * at the end of the file that don't have a newline present. Check for I/O
  1407. X * errors too. Return status.
  1408. X */
  1409. Xffgetline(buf, nbuf)
  1410. Xregister char   buf[];
  1411. X{
  1412. X        register int    c;
  1413. X        register int    i;
  1414. X
  1415. X        i = 0;
  1416. X
  1417. X        while ((c = fgetc(ffp)) != EOF && c != '\n') {
  1418. X                if (i >= nbuf-2) {
  1419. X            buf[nbuf - 2] = c;    /* store last char read */
  1420. X            buf[nbuf - 1] = 0;    /* and terminate it */
  1421. X                        mlwrite("File has long line");
  1422. X                        return (FIOLNG);
  1423. X                }
  1424. X                buf[i++] = c;
  1425. X        }
  1426. X
  1427. X        if (c == EOF) {
  1428. X                if (ferror(ffp)) {
  1429. X                        mlwrite("File read error");
  1430. X                        return (FIOERR);
  1431. X                }
  1432. X
  1433. X                if (i != 0) {
  1434. X                        mlwrite("File has funny line at EOF");
  1435. X                        return (FIOERR);
  1436. X                }
  1437. X                return (FIOEOF);
  1438. X        }
  1439. X
  1440. X        buf[i] = 0;
  1441. X        return (FIOSUC);
  1442. X}
  1443. *-*-END-of-fileio.c-*-*
  1444. echo x - hp150.c
  1445. sed 's/^X//' >hp150.c <<'*-*-END-of-hp150.c-*-*'
  1446. X/*
  1447. X * The routines in this file provide support for HP150 screens
  1448. X * and routines to access the Keyboard through KEYCODE mode.
  1449. X * It compiles into nothing if not an HP150 screen device.
  1450. X * added by Daniel Lawrence
  1451. X */
  1452. X
  1453. X#define    termdef    1            /* don't define "term" external */
  1454. X
  1455. X#include        <stdio.h>
  1456. X#include        "estruct.h"
  1457. X#include    "edef.h"
  1458. X
  1459. X#if     HP150
  1460. X
  1461. X#include    <dos.h>
  1462. X
  1463. X#define NROW    24                      /* Screen size.                 */
  1464. X#define NCOL    80                      /* Edit if you want to.         */
  1465. X#define    MARGIN    8            /* size of minimim margin and    */
  1466. X#define    SCRSIZ    64            /* scroll size for extended lines */
  1467. X#define BEL     0x07                    /* BEL character.               */
  1468. X#define ESC     0x1B                    /* ESC character.               */
  1469. X
  1470. Xextern  int     openhp();               /* Forward references.          */
  1471. Xextern  int     ttgetc();
  1472. Xextern  int     ttputc();
  1473. Xextern  int     ttflush();
  1474. Xextern  int     closehp();
  1475. Xextern  int     hp15move();
  1476. Xextern  int     hp15eeol();
  1477. Xextern  int     hp15eeop();
  1478. Xextern  int     hp15beep();
  1479. Xextern    int    gethpkey();
  1480. Xextern    int    hp15rev();
  1481. X
  1482. X/* weird to ascii translation table */
  1483. X
  1484. Xchar trans[][2] = {
  1485. X    0x24,    9,    /* tab */
  1486. X    0x25,    13,    /* ret */
  1487. X    0x27,    8,    /* backspace */
  1488. X    0x30,    48,    /* zero */
  1489. X    0x31,    49,    /* one */
  1490. X    0x32,    50,    /* two */
  1491. X    0x33,    51,    /* three */
  1492. X    0x34,    52,    /* four */
  1493. X    0x35,    53,    /* five */
  1494. X    0x36,    54,    /* six */
  1495. X    0x37,    55,    /* seven */
  1496. X    0x38,    56,    /* eight */
  1497. X    0x39,    57,    /* nine */
  1498. X    0x50,    13,    /* enter */
  1499. X    0x54,    27,    /* break -> ESC */
  1500. X    0x55,    27,    /* esc */
  1501. X    0x58,    24,    /* stop -> ^X */
  1502. X    0x70,    45,    /* N-minus */
  1503. X    0x71,    42,    /* N-asterisk */
  1504. X    0x72,    43,    /* N-plus */
  1505. X    0x73,    47,    /* N-slash */
  1506. X    0x74,    44,    /* N-comma */
  1507. X    0x75,    13,    /* N-enter */
  1508. X    0x76,    9,    /* N-tab */
  1509. X    0x77,    46    /* N-period */
  1510. X};
  1511. X
  1512. X#define NTRANS    sizeof(trans) / 2
  1513. X
  1514. Xunion REGS r;        /* register set for bios and dos (AGIOS) calls */
  1515. Xint capslock = 0;    /* caps lock flag */
  1516. X
  1517. X/*
  1518. X * Standard terminal interface dispatch table. Most of the fields point into
  1519. X * "termio" code.
  1520. X */
  1521. XTERM    term    = {
  1522. X        NROW-1,
  1523. X        NCOL,
  1524. X    MARGIN,
  1525. X    SCRSIZ,
  1526. X    openhp,
  1527. X        closehp,
  1528. X    gethpkey,
  1529. X        ttputc,
  1530. X        ttflush,
  1531. X        hp15move,
  1532. X        hp15eeol,
  1533. X        hp15eeop,
  1534. X        hp15beep,
  1535. X        hp15rev
  1536. X};
  1537. X
  1538. Xhp15move(row, col)
  1539. X{
  1540. X        ttputc(ESC);
  1541. X        ttputc('&');
  1542. X        ttputc('a');
  1543. X        hp15parm(col);
  1544. X        ttputc('c');
  1545. X        hp15parm(row);
  1546. X        ttputc('R');
  1547. X}
  1548. X
  1549. Xhp15eeol()
  1550. X{
  1551. X        ttputc(ESC);
  1552. X        ttputc('K');
  1553. X}
  1554. X
  1555. Xhp15eeop()
  1556. X{
  1557. X        ttputc(ESC);
  1558. X        ttputc('J');
  1559. X}
  1560. X
  1561. Xhp15rev(status)        /* change the reverse video status */
  1562. X
  1563. Xint status;    /* TRUE = on, FALSE = off */
  1564. X
  1565. X{
  1566. X    ttputc(ESC);
  1567. X    ttputc('&');
  1568. X    ttputc('d');
  1569. X    ttputc(status ? 'B': '@');
  1570. X}
  1571. X
  1572. Xhp15beep()
  1573. X{
  1574. X        ttputc(BEL);
  1575. X        ttflush();
  1576. X}
  1577. X
  1578. Xhp15parm(n)
  1579. Xregister int    n;
  1580. X{
  1581. X        register int    q;
  1582. X
  1583. X        q = n/10;
  1584. X        if (q != 0)
  1585. X                hp15parm(q);
  1586. X        ttputc((n%10) + '0');
  1587. X}
  1588. X
  1589. X
  1590. Xgethpkey()    /* get a key from the HP keyboard while in keycode mode */
  1591. X
  1592. X{
  1593. X    static int keepflag = 0;    /* kept ahead char flag */
  1594. X    static int keepchar = 0;    /* kept ehead flag */
  1595. X    int c;
  1596. X    int devid;            /* device ID */
  1597. X    int ctype;            /* type of character gotten */
  1598. X    int shiftb;            /* state of shift keys */
  1599. X    int i;
  1600. X    
  1601. X    /* if we are in an extended char sequence, finish it */
  1602. X    if (keepflag != 0) {
  1603. X        keepflag = 0;
  1604. X        return(keepchar);
  1605. X    }
  1606. X
  1607. X    /* grab the next 4 char sequence */
  1608. Xnext:    shiftb = ttgetc();
  1609. X    devid = ttgetc();
  1610. X    c = ttgetc();
  1611. X    ttgetc();        /* skip null byte */
  1612. X    
  1613. X    /* make sure we are from the keyboard */
  1614. X    if (devid != 192)
  1615. X        goto next;
  1616. X
  1617. X    /* if normal ascii, return it */
  1618. X    if ((shiftb & 0x80) == 0) {
  1619. X        if (capslock && c >= 'a' && c <= 'z')
  1620. X            c -= 32;
  1621. X        return(c);
  1622. X    }
  1623. X
  1624. X    /* check specifically for the caps lock key */
  1625. X    if (c == 0x56) {
  1626. X        capslock = ~capslock;
  1627. X        goto next;
  1628. X    }
  1629. X
  1630. X    /* check to see if it needs translation */
  1631. X    for (i=0; i < NTRANS; i++)
  1632. X        if (trans[i][0] == c)
  1633. X            return((int)trans[i][1]);
  1634. X
  1635. X    /* other wise, shove it in the keep char and return the leadin code */
  1636. X    keepchar = c;
  1637. X    keepflag = 1;
  1638. X    return(0);
  1639. X}
  1640. X
  1641. Xopenhp()        /* open the HP150 keyboard for input */
  1642. X
  1643. X{
  1644. X    revexist = TRUE;
  1645. X
  1646. X    /* define key charectoristics with AGIOS call (0, 40) */
  1647. X    defkey();
  1648. X
  1649. X    /* Turn on RAW mode with MSDOS call 44h */
  1650. X    rawon();
  1651. X
  1652. X    /* Turn off Control-C checking  MS-DOS 33h */
  1653. X    ckeyoff();
  1654. X
  1655. X    /* Turn on keycode mode with AGIOS call (0,43) */
  1656. X    keycon();
  1657. X}
  1658. X
  1659. Xclosehp()        /* close the HP150 keyboard for input */
  1660. X
  1661. X{
  1662. X    /* define key charectoristics with AGIOS call (0, 40) */
  1663. X    undefkey();
  1664. X    
  1665. X    /* Turn off RAW mode with MSDOS call 44h */
  1666. X    rawoff();
  1667. X
  1668. X    /* Turn on Control-C checking  MS-DOS 33h */
  1669. X    ckeyon();
  1670. X
  1671. X    /* Turn off keycode mode with AGIOS call (0,43) */
  1672. X    keycoff();
  1673. X}
  1674. X
  1675. Xrawon()        /* put the HP150 keyboard into RAW mode */
  1676. X
  1677. X{
  1678. X    /* get the IO control info */
  1679. X
  1680. X    r.x.ax = 0x4400;    /* IO ctrl get device information */
  1681. X    r.x.bx = 0x0001;    /* File handle; 1 for console */
  1682. X    intdos(&r, &r);        /* go fer it */
  1683. X
  1684. X    r.h.dh = 0;        /* clear high byte for put */
  1685. X    r.h.dl |= 0x20;        /* set raw bit */
  1686. X
  1687. X    /* and put it back */
  1688. X
  1689. X    r.x.ax = 0x4401;    /* IO ctrl put device information */
  1690. X    r.x.bx = 0x0001;    /* File handle; 1 for console */
  1691. X    intdos(&r, &r);        /* go fer it */
  1692. X}
  1693. X
  1694. Xrawoff()    /* put the HP150 keyboard into COOKED mode */
  1695. X
  1696. X{
  1697. X    /* get the IO control info */
  1698. X
  1699. X    r.x.ax = 0x4400;    /* IO ctrl get device information */
  1700. X    r.x.bx = 0x0001;    /* File handle; 1 for console */
  1701. X    intdos(&r, &r);        /* go fer it */
  1702. X
  1703. X    r.h.dh = 0;        /* clear high byte for put */
  1704. X    r.h.dl &= 0xdf;        /* set raw bit */
  1705. X
  1706. X    /* and put it back */
  1707. X
  1708. X    r.x.ax = 0x4401;    /* IO ctrl put device information */
  1709. X    r.x.bx = 0x0001;    /* File handle; 1 for console */
  1710. X    intdos(&r, &r);        /* go fer it */
  1711. X}
  1712. X
  1713. X
  1714. Xckeyoff()    /* turn control-C trapping off */
  1715. X
  1716. X{
  1717. X    r.h.ah = 0x33;    /* ctrl-break check */
  1718. X    r.h.al = 1;    /* set the state of the ctrl-break check */
  1719. X    r.h.dl = 0;    /* turn it off */
  1720. X    intdos(&r, &r);
  1721. X}
  1722. X
  1723. Xckeyon()    /* turn control-C trapping on */
  1724. X
  1725. X{
  1726. X    r.h.ah = 0x33;    /* ctrl-break check */
  1727. X    r.h.al = 1;    /* set the state of the ctrl-break check */
  1728. X    r.h.dl = 1;    /* turn it on */
  1729. X    intdos(&r, &r);
  1730. X}
  1731. X
  1732. Xagios(buf, len)    /* perform an AGIOS call */
  1733. X
  1734. Xchar *buf;    /* sequence of bytes in command */
  1735. Xint len;    /* length of command in bytes */
  1736. X
  1737. X{
  1738. X    r.x.ax = 0x4403;    /* I/O ctrl write */
  1739. X    r.x.bx = 1;        /* console handle */
  1740. X    r.x.cx = len;        /* buffer length */
  1741. X    r.x.dx = (unsigned)buf;    /* buffer address */
  1742. X    return(intdos(&r, &r));    /* do it */
  1743. X}
  1744. X
  1745. Xkeycon()    /* turn keycode mode on */
  1746. X
  1747. X{
  1748. X    static char cmd[] = {43, 0, 1};
  1749. X
  1750. X    return(agios(&cmd[0], 3));
  1751. X}
  1752. X
  1753. Xkeycoff()    /* turn keycode mode off */
  1754. X
  1755. X{
  1756. X    static char cmd[] = {43, 0, 0};
  1757. X
  1758. X    return(agios(&cmd[0], 3));
  1759. X}
  1760. X
  1761. Xdefkey()    /* change all special keys to intercept mode */
  1762. X
  1763. X{
  1764. X    static char cmd[] = {40, 0, 2, 0, 0xfe, 0};
  1765. X
  1766. X    return(agios(&cmd[0], 6));
  1767. X}
  1768. X
  1769. Xundefkey()    /* change all special keys to intercept mode */
  1770. X
  1771. X{
  1772. X    static char cmd[] = {40, 0, 0, 0, 0xfe, 0};
  1773. X
  1774. X    return(agios(&cmd[0], 6));
  1775. X}
  1776. X
  1777. X#else
  1778. X
  1779. Xh15hello()
  1780. X
  1781. X{
  1782. X}
  1783. X#endif
  1784. *-*-END-of-hp150.c-*-*
  1785. echo x - lock.c
  1786. sed 's/^X//' >lock.c <<'*-*-END-of-lock.c-*-*'
  1787. X/*    LOCK:    File locking command routines for MicroEMACS
  1788. X        written by Daniel Lawrence
  1789. X                                */
  1790. X
  1791. X#include <stdio.h>
  1792. X#include "estruct.h"
  1793. X#include "edef.h"
  1794. X
  1795. X#if    FILOCK
  1796. X#if    V7 & BSD
  1797. X#include <sys/errno.h>
  1798. X
  1799. Xextern int sys_nerr;        /* number of system error messages defined */
  1800. Xextern char *sys_errlist[];    /* list of message texts */
  1801. Xextern int errno;        /* current error */
  1802. X
  1803. Xchar *lname[NLOCKS];    /* names of all locked files */
  1804. Xint numlocks;        /* # of current locks active */
  1805. X
  1806. X/* lockchk:    check a file for locking and add it to the list */
  1807. X
  1808. Xlockchk(fname)
  1809. X
  1810. Xchar *fname;    /* file to check for a lock */
  1811. X
  1812. X{
  1813. X    register int i;        /* loop indexes */
  1814. X    register int status;    /* return status */
  1815. X    char *undolock();
  1816. X
  1817. X    /* check to see if that file is already locked here */
  1818. X    if (numlocks > 0)
  1819. X        for (i=0; i < numlocks; ++i)
  1820. X            if (strcmp(fname, lname[i]) == 0)
  1821. X                return(TRUE);
  1822. X
  1823. X    /* if we have a full locking table, bitch and leave */
  1824. X    if (numlocks == NLOCKS) {
  1825. X        mlwrite("LOCK ERROR: Lock table full");
  1826. X        return(ABORT);
  1827. X    }
  1828. X
  1829. X    /* next, try to lock it */
  1830. X    status = lock(fname);
  1831. X    if (status == ABORT)    /* file is locked, no override */
  1832. X        return(ABORT);
  1833. X    if (status == FALSE)    /* locked, overriden, dont add to table */
  1834. X        return(TRUE);
  1835. X
  1836. X    /* we have now locked it, add it to our table */
  1837. X    lname[++numlocks - 1] = (char *)malloc(strlen(fname) + 1);
  1838. X    if (lname[numlocks - 1] == NULL) {    /* malloc failure */
  1839. X        undolock(fname);        /* free the lock */
  1840. X        mlwrite("Cannot lock, out of memory");
  1841. X        --numlocks;
  1842. X        return(ABORT);
  1843. X    }
  1844. X
  1845. X    /* everthing is cool, add it to the table */
  1846. X    strcpy(lname[numlocks-1], fname);
  1847. X    return(TRUE);
  1848. X}
  1849. X
  1850. X/*    lockrel:    release all the file locks so others may edit */
  1851. X
  1852. Xlockrel()
  1853. X
  1854. X{
  1855. X    register int i;        /* loop index */
  1856. X    register int status;    /* status of locks */
  1857. X    register int s;        /* status of one unlock */
  1858. X
  1859. X    status = TRUE;
  1860. X    if (numlocks > 0)
  1861. X        for (i=0; i < numlocks; ++i) {
  1862. X            if ((s = unlock(lname[i])) != TRUE)
  1863. X                status = s;
  1864. X            free(lname[i]);
  1865. X        }
  1866. X    numlocks = 0;
  1867. X    return(status);
  1868. X}
  1869. X
  1870. X/* lock:    Check and lock a file from access by others
  1871. X        returns    TRUE = files was not locked and now is
  1872. X            FALSE = file was locked and overridden
  1873. X            ABORT = file was locked, abort command
  1874. X*/
  1875. X
  1876. Xlock(fname)
  1877. X
  1878. Xchar *fname;    /* file name to lock */
  1879. X
  1880. X{
  1881. X    register char *locker;    /* lock error message */
  1882. X    register int status;    /* return status */
  1883. X    char msg[NSTRING];    /* message string */
  1884. X    char *dolock();
  1885. X
  1886. X    /* attempt to lock the file */
  1887. X    locker = dolock(fname);
  1888. X    if (locker == NULL)    /* we win */
  1889. X        return(TRUE);
  1890. X
  1891. X    /* file failed...abort */
  1892. X    if (strncmp(locker, "LOCK", 4) == 0) {
  1893. X        lckerror(locker);
  1894. X        return(ABORT);
  1895. X    }
  1896. X
  1897. X    /* someone else has it....override? */
  1898. X    strcpy(msg, "File in use by ");
  1899. X    strcat(msg, locker);
  1900. X    strcat(msg, ", overide?");
  1901. X    status = mlyesno(msg);        /* ask them */
  1902. X    if (status == TRUE)
  1903. X        return(FALSE);
  1904. X    else
  1905. X        return(ABORT);
  1906. X}
  1907. X
  1908. X/*    unlock:    Unlock a file
  1909. X        this only warns the user if it fails
  1910. X                            */
  1911. X
  1912. Xunlock(fname)
  1913. X
  1914. Xchar *fname;    /* file to unlock */
  1915. X
  1916. X{
  1917. X    register char *locker;    /* undolock return string */
  1918. X    char *undolock();
  1919. X
  1920. X    /* unclock and return */
  1921. X    locker = undolock(fname);
  1922. X    if (locker == NULL)
  1923. X        return(TRUE);
  1924. X
  1925. X    /* report the error and come back */
  1926. X    lckerror(locker);
  1927. X    return(FALSE);
  1928. X}
  1929. X
  1930. Xlckerror(errstr)    /* report a lock error */
  1931. X
  1932. Xchar *errstr;        /* lock error string to print out */
  1933. X
  1934. X{
  1935. X    char obuf[NSTRING];    /* output buffer for error message */
  1936. X
  1937. X    strcpy(obuf, errstr);
  1938. X    strcat(obuf, " - ");
  1939. X    if (errno < sys_nerr)
  1940. X        strcat(obuf, sys_errlist[errno]);
  1941. X    else
  1942. X        strcat(obuf, "[can not get system error message]");
  1943. X    mlwrite(obuf);
  1944. X}
  1945. X#endif
  1946. X#else
  1947. Xlckhello()    /* dummy function */
  1948. X{
  1949. X}
  1950. X#endif
  1951. *-*-END-of-lock.c-*-*
  1952. exit
  1953.  
  1954.  
  1955.