home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #20 / NN_1992_20.iso / spool / comp / sources / unix / 268 < prev    next >
Encoding:
Text File  |  1992-09-08  |  75.2 KB  |  2,728 lines

  1. Newsgroups: comp.sources.unix
  2. Path: sparky!uunet!decwrl!deccrl!news.crl.dec.com!pa.dec.com!vixie
  3. From: klin@iat.uni-paderborn.de (Peter Klingebiel)
  4. Subject: v26i069: utree - screen oriented filesystem utility (V3.03b-um), Part06/08
  5. Message-ID: <1992Sep7.214944.27093@PA.dec.com>
  6. Originator: vixie@cognition.pa.dec.com
  7. Sender: unix-sources-moderator@pa.dec.com
  8. Organization: DEC Palo Alto
  9. Date: Mon, 7 Sep 92 21:49:44 GMT
  10. Approved: vixie@pa.dec.com
  11. Lines: 2715
  12.  
  13. Submitted-By: klin@iat.uni-paderborn.de (Peter Klingebiel)
  14. Posting-Number: Volume 26, Issue 69
  15. Archive-Name: utree/part06
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 6 (of 8)."
  24. # Contents:  src/file.c src/term.c
  25. # Wrapped by vixie@cognition.pa.dec.com on Mon Sep  7 14:39:57 1992
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'src/file.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'src/file.c'\"
  29. else
  30. echo shar: Extracting \"'src/file.c'\" \(41484 characters\)
  31. sed "s/^X//" >'src/file.c' <<'END_OF_FILE'
  32. X/*
  33. X *      FILE.C
  34. X *      UTREE file menu routines.
  35. X *      3.01-um klin, Tue Jun  4 14:20:31 1991
  36. X *              klin, Tue Oct 15 14:02:37 1991, Handling of symlinks changed
  37. X *              klin, Sat Oct 26 15:07:06 1991, Copying and moving changed
  38. X *                                              Sorting and zooming changed
  39. X *                                              Select directories added
  40. X *      3.02-um klin, Fri Nov  1 10:46:14 1991, Screen layout changed
  41. X *                                              Marking files changed
  42. X *                                              Bug in edit() deleted
  43. X *              klin, Sun Nov 24 19:30:43 1991, Cd to current directory before
  44. X *                                              executing some commands
  45. X *                                              Video attributes changed
  46. X *      3.03-um klin, Tue Feb 11 19:39:09 1992, Screen layout changed,
  47. X *                                              Variables and filetype commands
  48. X *                                              changed
  49. X *              klin, Sun Feb 23 17:32:31 1992, Key handling and key bindings
  50. X *                                              changed
  51. X *              klin, Fri Mar  6 08:18:38 1992, Minor changes in execute()
  52. X *
  53. X *      Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen.
  54. X *      For copying and distribution information see the file COPYRIGHT.
  55. X */
  56. X#ifndef lint
  57. static char sccsid[] = "@(#) utree 3.03-um (klin) Mar  6 1992 file.c";
  58. X#endif  /* !lint */
  59. X
  60. X#include "defs.h"
  61. X
  62. X/* ---- Local variables and definitions ------------------------------- */
  63. X
  64. LOCAL int flast;                /* Last current file                    */
  65. LOCAL int fmark;                /* Marked file                          */
  66. LOCAL int nscroll;              /* Lines to scroll                      */
  67. X
  68. X/* Default file menu commands in help line                              */
  69. LOCAL char *fmline =
  70. X" Help Copy Edit Find Grep Move List Print Remove Stat Tag Untag View Quit";
  71. LOCAL char *menuline = NULL;
  72. X
  73. X#define CUR(c)  ((c) >= 'a')    /* Command works on current file only   */
  74. X
  75. X/* ---- External variables and functions ------------------------------ */
  76. X
  77. XEXTRN char *selectdir();
  78. X
  79. X/* ---- Local/global functions and procedures ------------------------- */
  80. X
  81. X/*
  82. X *      FILE SCREEN UPDATE AND REFRESH
  83. X */
  84. X
  85. X/* Show file list from file f to file t */
  86. LOCAL VOID showfiles(f, t, c)
  87. X  register int f, t, c;
  88. X{
  89. X  if(c) {                       /* Clear file window */
  90. X    (void) cursorxy(0, firstline);
  91. X    clearwindow(firstline, lastline);
  92. X  }
  93. X  while(f < CNFIL && f < t && FFROW(cdlist, f) <= lastline)
  94. X    putfile(cdlist, f++, FF_TAG);
  95. X
  96. X} /* showfiles() */
  97. X
  98. X/* Update file screen */
  99. LOCAL VOID updatefiles()
  100. X{
  101. X  if(fileflag == SF_FULL)                       /* Full update */
  102. X    clearscreen();
  103. X  if(fileflag & SF_ECHO)                        /* Echo line */
  104. X    if(CZOOM)
  105. X      (void) putecho("%s/%s: %d file(s)", CPNAM, CZOOM, CNFIL);
  106. X    else
  107. X      (void) putecho("%s/*: %d file(s) %d dir(s)", CPNAM, CNFIL, CNDIR);
  108. X  if(fileflag & SF_HELP)                        /* Help line */
  109. X    putmenu("FILE:", menuline);
  110. X  if(fileflag & SF_TREE) {                      /* File window */
  111. X    if(CANSCROLL && nscroll < 0 && nscroll > (firstline-lastline)) {
  112. X      (void) windowup(firstline, lastline, -nscroll);
  113. X      showfiles(CFTOP+fperpage-fperline+(nscroll*fperline), CFTOP+fperpage, 0);
  114. X      if(flast >= 0)
  115. X       putfile(cdlist, flast, FF_TAG);
  116. X    }
  117. X    else if(CANSCROLL && nscroll > 0 && nscroll < (lastline-firstline)) {
  118. X      (void) windowdown(firstline, lastline, nscroll);
  119. X      showfiles(CFTOP, CFTOP + (nscroll * fperline) + fperline, 0);
  120. X      if(flast >= 0)
  121. X       putfile(cdlist, flast, FF_TAG);
  122. X    }
  123. X    else
  124. X      showfiles(CFTOP, CNFIL, fileflag != SF_FULL);
  125. X    nscroll = 0;
  126. X    fileflag |= SF_LIST;
  127. X  }
  128. X  else if(fileflag & SF_LAST && flast >= 0)     /* Last file */
  129. X    putfile(cdlist, flast, FF_TAG);
  130. X  if((fileflag & SF_LIST) && CNFIL > 0) {       /* Current file */
  131. X    putfile(cdlist, CFCUR, FF_TAG);
  132. X    flast = CFCUR;
  133. X  }
  134. X  if(CNFIL > 0)                                 /* Position to current file */
  135. X    (void) cursorxy(FFCOL(cdlist, CFCUR), FFROW(cdlist, CFCUR));
  136. X  else
  137. X    (void) cursorxy(0, firstline);
  138. X  fileflag = 0;                                 /* Reset fileflag */
  139. X
  140. X} /* updatefiles() */
  141. X
  142. X/*
  143. X *      MARK/TAG FILE
  144. X */
  145. X
  146. X/* Set mark w on file f */
  147. LOCAL VOID setmark(f, w)
  148. X  register int f, w;
  149. X{
  150. X  if(f >= CFTOP && f < (CFTOP + fperpage)) {
  151. X    putfile(cdlist, f, w);
  152. X    (void) cursorxy(FFCOL(cdlist, f), FFROW(cdlist, f));
  153. X    flushout();
  154. X  }
  155. X
  156. X} /* setmark() */
  157. X
  158. X/* Reset mark on file f */
  159. LOCAL VOID unsetmark(f)
  160. X  register int f;
  161. X{
  162. X  if(f >= CFTOP && f < (CFTOP + fperpage)) {
  163. X    putfile(cdlist, f, FF_TAG);
  164. X    (void) cursorxy(FFCOL(cdlist, f), FFROW(cdlist, f));
  165. X    flushout();
  166. X  }
  167. X
  168. X} /* unsetmark() */
  169. X
  170. X/* Tag single file f */
  171. LOCAL VOID tagfile(f)
  172. X  register int f;
  173. X{
  174. X  FITAG(cdlist, f) = FF_TAG;
  175. X  ++CNTAG;
  176. X  setmark(f, FF_TAG);
  177. X
  178. X} /* tagfile() */
  179. X
  180. X/* Untag single file f */
  181. LOCAL VOID untagfile(f)
  182. X  register int f;
  183. X{
  184. X  FITAG(cdlist, f) = FF_NONE;
  185. X  if(CNTAG > 0)
  186. X    --CNTAG;
  187. X
  188. X} /* untagfile() */
  189. X
  190. X/*
  191. X *      MOVE IN FILELIST
  192. X */
  193. X
  194. X/* Go forward or backward in file list */
  195. GLOBL int gofile(dp, dir)
  196. X  register dlist *dp;
  197. X  register int dir;
  198. X{
  199. X  register int l;
  200. X
  201. X  if(dir > 0 && (DFCUR(dp) + 1) < DNFIL(dp)) {  /* Next file */
  202. X    ++DFCUR(dp);
  203. X    fileflag |= SF_LIST;
  204. X    /* Out of bounds: Search for new top file */
  205. X    if(DFCUR(dp) >= (DFTOP(dp)+fperpage) && (DFTOP(dp)+fperpage) < DNFIL(dp)) {
  206. X      l = (lastline - firstline) / 2;
  207. X      while(l-- > 0 && (DFTOP(dp) + fperpage) < DNFIL(dp)) {
  208. X       DFTOP(dp) += fperline;
  209. X       --nscroll;
  210. X      }
  211. X      fileflag |= SF_TREE;
  212. X    }
  213. X    else
  214. X      fileflag |= SF_LAST;
  215. X  }
  216. X  else if(dir < 0 && DFCUR(dp) > 0) {           /* Previous file */
  217. X    --DFCUR(dp);
  218. X    fileflag |= SF_LIST;
  219. X    /* Out of bounds: Search for new top file */
  220. X    if(DFCUR(dp) <  DFTOP(dp) && DFTOP(dp) > 0) {
  221. X      l = (lastline - firstline) / 2;
  222. X      while(l-- > 0 && DFTOP(dp) > 0) {
  223. X       DFTOP(dp) -= fperline;
  224. X       ++nscroll;
  225. X      }
  226. X      fileflag |= SF_TREE;
  227. X    }
  228. X    else
  229. X      fileflag |= SF_LAST;
  230. X  }
  231. X  else
  232. X    return(0);
  233. X  return(1);
  234. X
  235. X} /* gofile() */
  236. X
  237. X/*
  238. X *      SCROLL FILE LIST
  239. X */
  240. X
  241. X/* Scroll up or down file list */
  242. LOCAL int scrollfile(dir)
  243. X  register int dir;
  244. X{
  245. X  if(dir < 0 && (CFTOP + fperpage) < CNFIL) {   /* Scroll up */
  246. X    CFTOP += fperline;
  247. X    if(CANSCROLL) {
  248. X      (void) windowup(firstline, lastline, 1);
  249. X      showfiles(CFTOP + fperpage - fperline, CFTOP + fperpage, 0);
  250. X      fileflag |= SF_MOVE;
  251. X    }
  252. X    else
  253. X      fileflag |= SF_TREE;
  254. X    if(CFCUR < CFTOP) {
  255. X      CFCUR += fperline;
  256. X      fileflag |= SF_LIST;
  257. X    }
  258. X  }
  259. X  else if(dir > 0 && CFTOP > 0) {               /* Scroll down */
  260. X    CFTOP -= fperline;
  261. X    if(CANSCROLL) {
  262. X      (void) windowdown(firstline, lastline, 1);
  263. X      showfiles(CFTOP, CFTOP + fperline, 0);
  264. X      fileflag |= SF_MOVE;
  265. X    }
  266. X    else
  267. X      fileflag |= SF_TREE;
  268. X    if(CFCUR >= (CFTOP + fperpage)) {
  269. X      CFCUR -= fperline;
  270. X      fileflag |= SF_LIST;
  271. X    }
  272. X  }
  273. X  else
  274. X    return(0);
  275. X  return(1);
  276. X
  277. X} /* scrollfile() */
  278. X
  279. X/*
  280. X *      SELECT DIRECTORY
  281. X */
  282. LOCAL char *doselect(what)
  283. X  register char *what;
  284. X{
  285. X  register char *dn;
  286. X
  287. X  dn = selectdir(what);
  288. X  fileflag = SF_FULL;
  289. X  fileflag &= ~(SF_HELP|SF_ECHO);
  290. X  updatefiles();
  291. X  return(dn);
  292. X
  293. X} /* doselect() */
  294. X
  295. X/*
  296. X *      LIST FILE(S)
  297. X */
  298. X
  299. X/* List file(s) in current file list */
  300. LOCAL int list(t)
  301. X  register int t;
  302. X{
  303. X  char pat[PATLEN];
  304. X  struct stat st;
  305. X  register char *ct;
  306. X  register int c, f, ff, l;
  307. X
  308. X  if(CNFIL == 0)                /* Nothing to list */
  309. X    return(RV_OK);
  310. X
  311. X  who = "LIST FILE";
  312. X  if(t || CNTAG <= 0) {
  313. X    puthelp("%s: Give file pattern (CR:all files)", who);
  314. X    if((c = getpattern(pat, "List which files:")) < RV_NUL)
  315. X      return(c);
  316. X    else if(c == RV_NUL)
  317. X      (void) strcpy(pat, "*");
  318. X    t = 1;
  319. X  }
  320. X
  321. X  /* Show all matching files */
  322. X  l = firstline;
  323. X  ff = 0;
  324. X  c = RV_OK;
  325. X  for(f = 0; f < CNFIL; f++) {
  326. X    if(( !t && ISTAG(cdlist, f)) || umatch(cdlist, f, pat) > 0) {
  327. X      if((*statfun)(FFNAM(cdlist, f), &st) != 0)
  328. X       continue;
  329. X      if(l == firstline) {
  330. X       if(ff > 0) {
  331. X         puthelp("%s %s (CR:continue  ELSE:quit)", who, pat);
  332. X         c = hitakey("Continue listing ?", echoline, DA_NONE);
  333. X         if( !(c == '\n' || c == ' '))
  334. X           break;
  335. X       }
  336. X       fileflag = SF_FULL;
  337. X       clearwindow(firstline, lastline);
  338. X      }
  339. X      ++ff;
  340. X      ct = ctime(&st.st_mtime);
  341. X      ct[strlen(ct) - 1] = '\0';
  342. X      (void) putfxy(0, l, 0, "%s  %8ld  %s  %s", fileaccess(&st), st.st_size, ct,
  343. X                   FFNAM(cdlist, f));
  344. X      if(++l > lastline)
  345. X       l = firstline;
  346. X    }
  347. X  }
  348. X
  349. X  if(c >= RV_NUL) {
  350. X    puthelp("%s %s", who, hitkey);
  351. X    if(t)
  352. X      (void) putecho("Listed %d file(s) matching %s", ff, pat);
  353. X    else
  354. X      (void) putecho("Listed %d tagged file(s)", ff);
  355. X    c = hitakey(NULL);
  356. X  }
  357. X  return(c);
  358. X
  359. X} /* list() */
  360. X
  361. X/*
  362. X *      SEARCH IN FILE(S)
  363. X */
  364. X
  365. X/* Search for pattern in file(s) */
  366. LOCAL int grep(one)
  367. X  register int one;
  368. X{
  369. X  char input[PATLEN];
  370. X  register int f, c;
  371. X
  372. X  if(CNFIL == 0)                /* Nothing to search */
  373. X    return(RV_OK);
  374. X
  375. X  who = "GREP FILE";
  376. X  puthelp("%s: Give pattern (CR:%s)", who, gpattern[0] ? gpattern : "quit");
  377. X  c = putecho("Search for pattern in file:");
  378. X  if((c = getline(input, sizeof(input), c, 0, NULL, GNULL, 0)) == RV_OK)
  379. X    (void) strcpy(gpattern, input);
  380. X  else if(c < RV_NUL || (c == RV_NUL && gpattern[0] == '\0'))
  381. X    return(c);
  382. X
  383. X  if( !one && CNTAG) {          /* Tagged files */
  384. X    c = RV_NUL; f = -1;
  385. X    do {
  386. X      ++f;
  387. X      if(ISTAG(cdlist, f)) {    /* File tagged */
  388. X       untagfile(f);
  389. X       setmark(f, FF_MARK);
  390. X       (void) putecho("Searching in %s", FFNAM(cdlist, f));
  391. X       flushout();
  392. X       if((c = grepfile(cdlist, f)) == RV_OK) {
  393. X         puthelp("%s (CR:next  SP:select  M:mark  T:tag  ELSE:quit)", who);
  394. X         (void) putecho("Found \'%s\' -> %s:", gpattern, FFNAM(cdlist, f));
  395. X         c = hitakey(NULL);
  396. X         unsetmark(f);
  397. X         if(c == 't') {
  398. X           tagfile(f);
  399. X           c = '\n';
  400. X         }
  401. X         else if(c == 'm') {
  402. X           fmark = f;
  403. X           c = '\n';
  404. X         }
  405. X         else if(c == ' ')
  406. X           while(f != CFCUR)
  407. X             (void) gofile(cdlist, f > CFCUR ? 1 : -1);
  408. X       }
  409. X       else
  410. X         unsetmark(f);
  411. X      }
  412. X    } while(f < CNFIL && (c == RV_NUL || c == '\n'));
  413. X  }
  414. X  else if((c = grepfile(cdlist, CFCUR)) == RV_OK) {     /* Current file */
  415. X    puthelp("%s %s", who, hitkey);
  416. X    (void) putecho("Found \'%s\'", gpattern);
  417. X    c = hitakey(NULL);
  418. X  }
  419. X
  420. X  if(c)
  421. X    return(c);
  422. X  puthelp("%s: %s %s", who, gpattern, hitkey);
  423. X  return(errequest(gpattern, "Not found"));
  424. X
  425. X} /* grep() */
  426. X
  427. X/*
  428. X *      FIND FILE(S)
  429. X */
  430. X
  431. X/* Find file(s) in current file list */
  432. LOCAL int find(one)
  433. X  register int one;
  434. X{
  435. X  char input[PATLEN];
  436. X  register int f, c;
  437. X
  438. X  if(CNFIL == 0)                /* Nothing to find */
  439. X    return(RV_OK);
  440. X
  441. X  who = "FIND FILE";
  442. X  puthelp("%s: Give file pattern (CR:%s)", who, fpattern[0] ? fpattern : "quit");
  443. X  if((c = getpattern(input, "Find which file:")) == RV_OK)
  444. X    (void) strcpy(fpattern, input);
  445. X  else if(c < RV_NUL || (c == RV_NUL && fpattern[0] == '\0'))
  446. X    return(c);
  447. X
  448. X  f = one ? CFCUR : -1;
  449. X  do {
  450. X    ++f;
  451. X    if((c = findfile(cdlist, f)) == RV_OK) {
  452. X      setmark(f, FF_MARK);
  453. X      puthelp("%s (CR:next  SP:select  M:mark  T:tag  ELSE:quit)", who);
  454. X      (void) putecho("Found %s:", FFNAM(cdlist, f));
  455. X      c = hitakey(NULL);
  456. X      unsetmark(f);
  457. X      if(c == 't') {
  458. X       tagfile(f);
  459. X       c = '\n';
  460. X      }
  461. X      else if(c == 'm') {
  462. X       fmark = f;
  463. X       c = '\n';
  464. X      }
  465. X      else if(c == ' ')
  466. X       while(f != CFCUR)
  467. X         (void) gofile(cdlist, f > CFCUR ? 1 : -1);
  468. X    }
  469. X  } while(f < CNFIL && (c == RV_NUL || c == '\n'));
  470. X
  471. X  if(c)
  472. X    return(c);
  473. X
  474. X  puthelp("%s: %s %s", who, fpattern, hitkey);
  475. X  return(errequest(fpattern, "Not found"));
  476. X
  477. X} /* find() */
  478. X
  479. X/*
  480. X *      FILE STATUS AND CHANGES
  481. X */
  482. X
  483. X/* Status information(s)/change(s) for current or tagged file(s) */
  484. LOCAL int status(one, s)
  485. X  register int one, s;
  486. X{
  487. X  register int f, c;
  488. X
  489. X  if(CNFIL == 0)                /* No need for status of nothing */
  490. X    return(RV_OK);
  491. X
  492. X  if( !one && CNTAG) {          /* Tagged files */
  493. X    for(f = 0; f < CNFIL; f++)
  494. X      if(ISTAG(cdlist, f)) {
  495. X       untagfile(f);
  496. X       if(s)
  497. X         c = statusfile(FFNAM(cdlist, f), 1);
  498. X       else {
  499. X         setmark(f, FF_MARK);
  500. X         c = infofile(f, CNTAG > 0);
  501. X         unsetmark(f);
  502. X       }
  503. X       if( !(c == RV_NUL || c == '\n' || c == ' '))
  504. X         break;
  505. X      }
  506. X  }
  507. X  else {
  508. X    if(s)
  509. X      c = statusfile(FFNAM(cdlist, CFCUR), 1);    /* Current files */
  510. X    else
  511. X      c = infofile(CFCUR, 0);
  512. X  }
  513. X
  514. X  if(buildflag)                 /* Rebuilding needed */
  515. X    CFLAG = FL_CHG;
  516. X  return(c);
  517. X
  518. X} /* status() */
  519. X
  520. X/* Display size and modification time of file f */
  521. LOCAL int infofile(f, h)
  522. X  register int f, h;
  523. X{
  524. X  struct stat st;
  525. X
  526. X  who = "INFO FILE";
  527. X  if((*statfun)(FFNAM(cdlist, f), &st)) {
  528. X    puthelp("%s %s", who, hitkey);
  529. X    return(errequest(FFNAM(cdlist, f), "Cannot stat"));
  530. X  }
  531. X  if(h)
  532. X    puthelp("%s %s (CR:continue  ELSE:quit)", who, FFNAM(cdlist, f));
  533. X  else
  534. X    puthelp("%s %s %s", who, FFNAM(cdlist, f), hitkey);
  535. X  (void) putecho("Access:%s Size:%ld Date:%s",
  536. X                 fileaccess(&st), st.st_size, ctime(&st.st_mtime));
  537. X  return(hitakey(NULL));
  538. X
  539. X} /* infofile() */
  540. X
  541. X/*
  542. X *      MOVE OR RENAME FILE(S)
  543. X */
  544. X
  545. X/* Move current or tagged file(s) */
  546. LOCAL int move(one)
  547. X  register int one;
  548. X{
  549. X  struct stat st;
  550. X  char name[NAMELEN];
  551. X  register char *to;
  552. X  register int f, c, req;
  553. X
  554. X  if(CNFIL == 0)                /* Nothing to move */
  555. X    return(RV_OK);
  556. X
  557. X  who = "MOVE FILE";
  558. X  if( !one && CNTAG) {          /* Tagged files */
  559. X    puthelp("%s: Give destination directory (CR:select one)", who);
  560. X    c = putecho("Move tagged files to:");
  561. X    if((c = getline(name, sizeof(name), c, 0, NULL, CLIST, 0)) < RV_NUL)
  562. X      return(c);
  563. X    if(c == RV_OK) {
  564. X      to = strcpy(name, pathname(name, CPNAM));
  565. X      if((*statfun)(to, &st) < 0) {
  566. X       puthelp("%s %s", who, hitkey);
  567. X       return(errequest(name, "Cannot stat"));
  568. X      }
  569. X      else if(STFMT(&st) != S_IFDIR) {
  570. X       puthelp("%s %s", who, hitkey);
  571. X       return(errequest(name, "Is not a directory"));
  572. X      }
  573. X    }
  574. X    else if((to = doselect("moving files")) == NULL) {
  575. X      fileflag |= SF_ECHO|SF_HELP;
  576. X      return(RV_NUL);
  577. X    }
  578. X    puthelp("%s (N:don't request  Q:quit  ELSE:request)", who);
  579. X    (void) putecho("Request before moving to %s ?", to);
  580. X    c = hitakey(NULL);
  581. X    if(c == 'q' || c < RV_NUL)
  582. X      return(c);
  583. X    if(req = (c != 'n'))
  584. X      puthelp("%s (Y:move  Q:quit  ELSE:don't move)", who);
  585. X    for(f = 0; f < CNFIL; f++)
  586. X      if(ISTAG(cdlist, f)) {
  587. X       untagfile(f);
  588. X       setmark(f, FF_MARK);
  589. X       c = movefile(cdlist, f, to, req);
  590. X       unsetmark(f);
  591. X       if(c == 'q' || c < RV_NUL)
  592. X         break;
  593. X      }
  594. X  }
  595. X  else {                        /* Current file */
  596. X    puthelp("%s: Give destination (CR:select directory)", who);
  597. X    c = putecho("Move file to:");
  598. X    if((c = getline(name, sizeof(name), c, 0, NULL, CLIST, 0)) < RV_NUL)
  599. X      return(c);
  600. X    else if(c == RV_OK)
  601. X      to = strcpy(name, pathname(name, CPNAM));
  602. X    else if((to = doselect("moving file")) == NULL) {
  603. X      fileflag |= SF_ECHO|SF_HELP;
  604. X      return(RV_NUL);
  605. X    }
  606. X    c = movefile(cdlist, CFCUR, to, 0);
  607. X  }
  608. X
  609. X  checkdlist(to);               /* Directory needs checking */
  610. X  ++buildflag;                  /* Set rebuild flags */
  611. X  CFLAG = FL_CHG;
  612. X  fileflag |= SF_ECHO|SF_HELP;
  613. X  return(c);
  614. X
  615. X} /* move() */
  616. X
  617. X/*
  618. X *      VIEW FILE(S)
  619. X */
  620. X
  621. X/* View current or tagged file(s) */
  622. LOCAL int view(one)
  623. X  register int one;
  624. X{
  625. X  register int f, c;
  626. X
  627. X  if(CNFIL == 0)                /* Nothing to view */
  628. X    return(RV_OK);
  629. X
  630. X  if( !one && CNTAG) {          /* Tagged files */
  631. X    for(f = 0; f < CNFIL; f++)
  632. X      if(ISTAG(cdlist, f)) {
  633. X       untagfile(f);
  634. X       if((c = viewfile(f, 0)) == 'n' || c < RV_NUL)
  635. X         break;
  636. X      }
  637. X  }
  638. X  else                          /* Current file */
  639. X    c = viewfile(CFCUR, 1);
  640. X
  641. X  return(c);
  642. X
  643. X} /* view() */
  644. X
  645. X/* View single file f */
  646. LOCAL int viewfile(f, one)
  647. X  register int f, one;
  648. X{
  649. X  char name[NAMELEN], buf[EXECLEN];
  650. X  register FILE *file;
  651. X  register int c, n;
  652. X
  653. X  /* Check if viewing is allowed */
  654. X  if( !isallowed(FFNAM(cdlist, f), (int) FMODE(cdlist, f)))
  655. X    return(hitakey(NULL));
  656. X
  657. X  who = "VIEW FILE";
  658. X  /* Simple check for text or binary file. May fail! */
  659. X  (void) strcpy(name, pathname(FFNAM(cdlist, f), CPNAM));
  660. X  if(file = fopen(name, "r")) {
  661. X    n = fread(buf, sizeof(char), 4, file);
  662. X    (void) fclose(file);
  663. X  }
  664. X  else
  665. X    return(errequest(FFNAM(cdlist, f), "Cannot open"));
  666. X
  667. X  if(n <= 0)                    /* File is empty */
  668. X    return(errequest(FFNAM(cdlist, f), "Is empty"));
  669. X  else if(istextfile(buf, n)) { /* Text file */
  670. X    (void) sprintf(buf, "%s %s %s", VARVAL(V_PG), VARVAL(V_PGO), name);
  671. X    (void) callsystem(buf, 1, 1);
  672. X  }
  673. X  else {                        /* Binary file */
  674. X    puthelp("%s (Y:hex dump  ELSE:don't view)", who);
  675. X    (void) putecho("File %s is not a text file, hex dump ?", FFNAM(cdlist, f));
  676. X    if((c = hitakey(NULL)) != 'y')
  677. X      return(c);
  678. X    (void) sprintf(buf, "%s %s %s|%s %s", VARVAL(V_XD), VARVAL(V_XDO), name,
  679. X                                         VARVAL(V_PG), VARVAL(V_PGO));
  680. X    (void) callsystem(buf, 1, 1);
  681. X  }
  682. X
  683. X  if(one || CNTAG < 1)
  684. X    return(hitakey("Viewing done (Hit a key)", lines-1, DA_REVERSE));
  685. X  else
  686. X    return(hitakey("Continue (N:no  ELSE:yes) ?", lines-1, DA_REVERSE));
  687. X
  688. X} /* viewfile() */
  689. X
  690. X/* Simple check if a file is a text file */
  691. LOCAL int istextfile(s, n)
  692. X  register char *s;
  693. X  register int n;
  694. X{
  695. X  while(--n > 0) {                      /* Simple check if all n chars */
  696. X    if( !(isprint(*s) || isspace(*s)))  /* are printable or whitespace */
  697. X      return(0);
  698. X    ++s;
  699. X  }
  700. X  return(1);
  701. X
  702. X} /* istextfile() */
  703. X
  704. X/*
  705. X *      PRINT FILE(S)
  706. X */
  707. X
  708. X/* Print current or tagged file(s) */
  709. LOCAL int print(one)
  710. X  register int one;
  711. X{
  712. X  register int f, c;
  713. X
  714. X  if(CNFIL == 0)                /* Nothing to print */
  715. X    return(RV_OK);
  716. X
  717. X  who = "PRINT FILE";
  718. X  if( !one && CNTAG) {          /* Tagged files */
  719. X    for(f = 0; f < CNFIL; f++)
  720. X      if(ISTAG(cdlist, f)) {
  721. X       untagfile(f);
  722. X       setmark(f, FF_MARK);
  723. X       puthelp("%s (Y:print  Q:quit  ELSE:don't print)", who);
  724. X       c = printfile(f, 1);
  725. X       unsetmark(f);
  726. X       if(c == 'q' || c < RV_NUL)
  727. X         break;
  728. X      }
  729. X  }
  730. X  else                          /* Current file */
  731. X    c = printfile(CFCUR, 0);
  732. X
  733. X  if(c < RV_NUL || one || !CNTAG)
  734. X    return(c);
  735. X  puthelp("%s %s", who, hitkey);
  736. X  return(hitakey("Printing done", echoline, DA_NONE));
  737. X
  738. X} /* print() */
  739. X
  740. X/* Print single file f with request if req is set */
  741. LOCAL int printfile(f, req)
  742. X  register int f, req;
  743. X{
  744. X  char name[NAMELEN], buf[EXECLEN];
  745. X  register int c;
  746. X
  747. X  (void) strcpy(name, pathname(FFNAM(cdlist, f), CPNAM));
  748. X  if(req) {
  749. X    (void) putecho("Print %s ?", name);
  750. X    if((c = hitakey(NULL)) != 'y')
  751. X      return(c);
  752. X  }
  753. X  (void) putecho("Printing %s", name);
  754. X  (void) sprintf(buf, "%s %s %s", VARVAL(V_LP), VARVAL(V_LPO), name);
  755. X  if((c = callsystem(buf, 0, 0)) != RV_OK)
  756. X    return(errequest(FFNAM(cdlist, f), "Error in printing"));
  757. X  return(RV_OK);
  758. X
  759. X} /* printfile() */
  760. X
  761. X/*
  762. X *      REMOVE FILE(S)
  763. X */
  764. X
  765. X/* Remove current or tagged file(s) */
  766. LOCAL int remove(one)
  767. X  register int one;
  768. X{
  769. X  register int f, c, req;
  770. X
  771. X  if(CNFIL == 0)                /* Nothing to remove */
  772. X    return(RV_OK);
  773. X
  774. X  who = "REMOVE FILE";
  775. X  if( !one && CNTAG) {          /* Tagged files */
  776. X    if(CNTAG > 1) {
  777. X      puthelp("%s (N:don't request  Q:quit  ELSE:request)", who);
  778. X      c = hitakey("Request before removing ?", echoline, DA_NONE);
  779. X      if(c == 'q' || c < RV_NUL)
  780. X       return(c);
  781. X      else if(req = (c != 'n'))
  782. X       puthelp("%s (Y:remove  Q:quit  ELSE:don't remove)", who);
  783. X    }
  784. X    else
  785. X      req = 1;
  786. X    for(f = CNFIL - 1; f >= 0; f--) {
  787. X      if(ISTAG(cdlist, f)) {
  788. X       untagfile(f);
  789. X       setmark(f, FF_MARK);
  790. X       if((c = removefile(cdlist, f, req)) != RV_OK)
  791. X         unsetmark(f);
  792. X       if(c == 'q' || c < RV_NUL)
  793. X         break;
  794. X      }
  795. X    }
  796. X  }
  797. X  else {                        /* Current file */
  798. X    puthelp("%s (Y:remove  ELSE:don't remove)", who);
  799. X    c = removefile(cdlist, CFCUR, 1);
  800. X  }
  801. X
  802. X  return(c);
  803. X
  804. X} /* remove() */
  805. X
  806. X/*
  807. X *      EDIT FILE(S)
  808. X */
  809. X
  810. X/* Edit current or tagged file(s) */
  811. LOCAL int edit(one)
  812. X  register int one;
  813. X{
  814. X  char name[FILELEN];
  815. X  register char *fname;
  816. X  register int f, c, mode, req;
  817. X
  818. X  who = "EDIT FILE";
  819. X  if( !one && CNTAG) {          /* Tagged files */
  820. X    if(CNTAG > 1) {
  821. X      puthelp("%s (N:don't request  Q:quit  ELSE:request)", who);
  822. X      c = hitakey("Request before edit ?", echoline, DA_NONE);
  823. X      if(c == 'q' || c < RV_NUL)
  824. X       return(c);
  825. X      else if(req = (c != 'n'))
  826. X       puthelp("%s (Y:edit  Q:quit  ELSE:don't edit)", who);
  827. X    }
  828. X    else
  829. X      req = 1;
  830. X    for(f = 0; f < CNFIL; f++)
  831. X      if(ISTAG(cdlist, f)) {
  832. X       untagfile(f);
  833. X       c = editfile(FFNAM(cdlist, f), (int) FMODE(cdlist, f), req);
  834. X       if(c == 'q' || c < RV_NUL)
  835. X         break;
  836. X      }
  837. X  }
  838. X  else {                        /* Current or no files */
  839. X    if(CNFIL > 0) {
  840. X      setmark(CFCUR, FF_MARK);
  841. X      puthelp("%s: Give file name (CR:%s)", who, FFNAM(cdlist, CFCUR));
  842. X      c = putecho("Edit file:");
  843. X      c = getline(name, sizeof(name), c, 0, NULL, GNULL, 0);
  844. X      unsetmark(CFCUR);
  845. X      if(c < RV_NUL)
  846. X       return(c);
  847. X    }
  848. X    else {                      /* Directory is empty */
  849. X      puthelp("%s: Give file name (CR:quit)", who);
  850. X      c = putecho("Edit which file:");
  851. X      if((c = getline(name, sizeof(name), c, 0, NULL, GNULL, 0)) != RV_OK)
  852. X       return(c);
  853. X    }
  854. X    fname = c == RV_NUL ? FFNAM(cdlist, CFCUR) : name;
  855. X    mode  = c == RV_NUL ? FMODE(cdlist, CFCUR) : FF_NONE;
  856. X    c = editfile(fname, mode, 0);
  857. X  }
  858. X
  859. X  return(c);
  860. X
  861. X} /* edit() */
  862. X
  863. X/* Edit single file name (mode mode) with request if req is set */
  864. LOCAL int editfile(name, mode, req)
  865. X  register char *name;
  866. X  register int mode, req;
  867. X{
  868. X  char pname[NAMELEN], buf[EXECLEN];
  869. X  register int c;
  870. X
  871. X  /* Check if editing is allowed */
  872. X  if( !isallowed(name, mode))
  873. X    return(hitakey(NULL));
  874. X
  875. X  (void) strcpy(pname, pathname(name, CPNAM));
  876. X  if(req) {
  877. X    (void) putecho("Edit %s ?", name);
  878. X    c = hitakey(NULL);
  879. X    if(c != 'y')
  880. X      return(c);
  881. X  }
  882. X  (void) sprintf(buf, "%s %s %s", VARVAL(V_ED), VARVAL(V_EDO), pname);
  883. X  (void) callsystem(buf, 1, 1);
  884. X
  885. X  checkdlist(CPNAM);            /* Directory needs checking */
  886. X  return(RV_OK);
  887. X
  888. X} /* editfile() */
  889. X
  890. X/*
  891. X *      COPY FILE(S)
  892. X */
  893. X
  894. X/* Copy current or tagged file(s) */
  895. LOCAL int copy(one)
  896. X  register int one;
  897. X{
  898. X  struct stat st;
  899. X  char name[NAMELEN];
  900. X  register char *to;
  901. X  register int f, c, req;
  902. X
  903. X  if(CNFIL == 0)                /* Nothing to copy */
  904. X    return(RV_OK);
  905. X
  906. X  who = "COPY FILE";
  907. X  if( !one && CNTAG) {          /* Tagged files */
  908. X    puthelp("%s: Give destination directory (CR:select one)", who);
  909. X    c = putecho("Copy tagged files to:");
  910. X    if((c = getline(name, sizeof(name), c, 0, NULL, CLIST, 0)) < RV_NUL)
  911. X      return(c);
  912. X    if(c == RV_OK) {
  913. X      to = strcpy(name, pathname(name, CPNAM));
  914. X      if((*statfun)(to, &st) < 0) {
  915. X       puthelp("%s %s", who, hitkey);
  916. X       return(errequest(name, "Cannot stat"));
  917. X      }
  918. X      else if(STFMT(&st) != S_IFDIR) {
  919. X       puthelp("%s %s", who, hitkey);
  920. X       return(errequest(name, "Is not a directory"));
  921. X      }
  922. X    }
  923. X    else if((to = doselect("copying files")) == NULL) {
  924. X      fileflag |= SF_ECHO|SF_HELP;
  925. X      return(RV_NUL);
  926. X    }
  927. X    puthelp("%s (N:don't request  Q:quit  ELSE:request)", who);
  928. X    (void) putecho("Request before copying to %s ?", to);
  929. X    c = hitakey(NULL);
  930. X    if(c == 'q' || c < RV_NUL)
  931. X      return(c);
  932. X    if(req = (c != 'n'))
  933. X      puthelp("%s (Y:copy  Q:quit  ELSE:don't copy)", who);
  934. X    for(f = 0; f < CNFIL; f++)
  935. X      if(ISTAG(cdlist, f)) {
  936. X       untagfile(f);
  937. X       setmark(f, FF_MARK);
  938. X       c = copyfile(cdlist, f, to, req);
  939. X       unsetmark(f);
  940. X       if(c == 'q' || c < RV_NUL)
  941. X         break;
  942. X      }
  943. X  }
  944. X  else {                        /* Current file */
  945. X    puthelp("%s: Give destination (CR:select directory)", who);
  946. X    c = putecho("Copy file to:");
  947. X    if((c = getline(name, sizeof(name), c, 0, NULL, CLIST, 0)) < RV_NUL)
  948. X      return(c);
  949. X    else if(c == RV_OK)
  950. X      to = strcpy(name, pathname(name, CPNAM));
  951. X    else if((to = doselect("copying file")) == NULL) {
  952. X      fileflag |= SF_ECHO|SF_HELP;
  953. X      return(RV_NUL);
  954. X    }
  955. X    c = copyfile(cdlist, CFCUR, to, 0);
  956. X  }
  957. X
  958. X  checkdlist(to);               /* Directory needs checking */
  959. X  fileflag |= SF_ECHO|SF_HELP;
  960. X  return(c);
  961. X
  962. X} /* copy() */
  963. X
  964. X/*
  965. X *      ZOOM FILES
  966. X */
  967. X
  968. X/* Get zoom pattern and rebuild filelist */
  969. LOCAL int zoomfile()
  970. X{
  971. X  char pat[PATLEN];
  972. X  register int c;
  973. X
  974. X  who = "ZOOM FILE";
  975. X  puthelp("%s: Give file pattern (CR:all files)", who);
  976. X  if((c = getpattern(pat, "Zoom which files:")) < RV_NUL)
  977. X    return(c);
  978. X  if(zoomlist(cdlist, pat))
  979. X    fileflag |= SF_TREE;
  980. X  return(RV_OK);
  981. X
  982. X} /* zoomfile() */
  983. X
  984. X/*
  985. X *      GOTO DIRECTORY / PARENT DIRECTORY
  986. X */
  987. X
  988. X/* Goto directory */
  989. LOCAL int gotodirectory()
  990. X{
  991. X#ifdef  S_IFLNK
  992. X  struct stat st;
  993. X#endif  /* S_IFLNK */
  994. X  register dlist *dp;
  995. X  register int lev, c;
  996. X
  997. X  if(CNFIL == 0)                /* Nothing to change to */
  998. X    return(RV_OK);
  999. X
  1000. X  who = "GOTO DIRECTORY";
  1001. X  puthelp("%s: %s", who, FFNAM(cdlist, CFCUR));
  1002. X  if(FMODE(cdlist, CFCUR) != FF_DIR) {
  1003. X#ifdef  S_IFLNK
  1004. X    if( !(FMODE(cdlist, CFCUR) == FF_SLNK && ISDIR(FFNAM(cdlist, CFCUR), st)))
  1005. X#endif  /* S_IFLNK */
  1006. X    return(errequest(FFNAM(cdlist, CFCUR), "Is not a directory"));
  1007. X  }
  1008. X
  1009. X  /* Search directory in directory tree */
  1010. X  for(dp = (dlist *) CNEXT, lev = CLEVL+1; dp && DLEVL(dp) > CLEVL; dp = (dlist *) DNEXT(dp))
  1011. X    if(DLEVL(dp) == lev && EQU(FFNAM(cdlist, CFCUR), DFNAM(dp)))
  1012. X      break;
  1013. X  /* Directory is not yet in directory tree */
  1014. X  if(dp == DNULL || DLEVL(dp) != lev)
  1015. X    dp = newdlist(FFNAM(cdlist, CFCUR), FL_NUL);
  1016. X
  1017. X  /* Directory file list must be read in */
  1018. X  if((DFLAG(dp) != FL_FIL || changedlist(dp)) && (c = newflist(dp)) != RV_OK)
  1019. X    return(c);
  1020. X
  1021. X  if( !DCANC(dp))
  1022. X    return(errequest(DFNAM(dp), "Cannot change"));
  1023. X  else if(DNFIL(dp) == 0) {
  1024. X    puthelp("%s: %s (y:change  ELSE:don't change)", who, DFNAM(dp));
  1025. X    c = errequest(DFNAM(dp), "Is empty, change anyway ?");
  1026. X    if(c != 'y')
  1027. X      return(c);
  1028. X  }
  1029. X
  1030. X  /* Position to directory in directory tree and return */
  1031. X  while(cdlist != dp)
  1032. X    (void) gotree(1);
  1033. X
  1034. X  return(RV_DIR);
  1035. X
  1036. X} /* gotodirectory() */
  1037. X
  1038. X/* Goto parent directory */
  1039. LOCAL int gotoparent()
  1040. X{
  1041. X  register char *name;
  1042. X  register int lev, c;
  1043. X
  1044. X  if(cdlist == droot)           /* Root has no parent */
  1045. X    return(RV_RET);
  1046. X
  1047. X  /* Position to parent directory in directory tree */
  1048. X  name = CFNAM;
  1049. X  lev  = CLEVL - 1;
  1050. X  while(CLEVL != lev)
  1051. X    (void) gotree(-1);
  1052. X  /* Parent directory needs rebuilding */
  1053. X  if((CFLAG != FL_FIL || changedlist(cdlist))
  1054. X     && (c = newflist(cdlist)) != RV_OK)
  1055. X    return(c);
  1056. X  /* Position to where we came from in parent directory file list */
  1057. X  CFCUR = CFTOP = 0;
  1058. X  while(CMP(name, FFNAM(cdlist, CFCUR)) && CFCUR < CNFIL)
  1059. X    (void) gofile(cdlist, 1);
  1060. X
  1061. X  return(RV_DIR);
  1062. X
  1063. X} /* gotoparent() */
  1064. X
  1065. X/*
  1066. X *      TAG / UNTAG FILE(S)
  1067. X */
  1068. X
  1069. X/* Tag current or selected file(s) */
  1070. LOCAL int tag(one)
  1071. X  register int one;
  1072. X{
  1073. X  char input[PATLEN];
  1074. X  register int f, c;
  1075. X
  1076. X  if(CNFIL == 0)                /* Nothing to tag */
  1077. X    return(RV_OK);
  1078. X
  1079. X  who = "TAG FILE";
  1080. X  if( !one) {                   /* Multiple files */
  1081. X    puthelp("%s: Give file pattern (CR:%s)", who, tpattern[0] ? tpattern : "quit");
  1082. X    if((c = getpattern(input, "Tag which file:")) == RV_OK)
  1083. X      (void) strcpy(tpattern, input);
  1084. X    else if(c < RV_NUL || (c == RV_NUL && tpattern[0] == '\0'))
  1085. X      return(c);
  1086. X  }
  1087. X  if(one)                       /* Currrent file */
  1088. X    tagfile(CFCUR);
  1089. X  else                          /* Matching files */
  1090. X    for(f = 0; f < CNFIL; f++)
  1091. X      if(umatch(cdlist, f, tpattern) > 0)
  1092. X       tagfile(f);
  1093. X
  1094. X  return(RV_OK);
  1095. X
  1096. X} /* tag() */
  1097. X
  1098. X/* Untag current or selected file(s) */
  1099. LOCAL int untag(one)
  1100. X  register int one;
  1101. X{
  1102. X  char pattern[PATLEN];
  1103. X  register int f, c;
  1104. X
  1105. X  if(CNFIL == 0)                /* Nothing to untag */
  1106. X    return(RV_OK);
  1107. X
  1108. X  who = "UNTAG FILE";
  1109. X  if( !one) {                   /* Multiple files */
  1110. X    setmark(CFCUR, FF_MARK);
  1111. X    puthelp("%s: Give file pattern (CR:all files)", who);
  1112. X    c = getpattern(pattern, "Untag which file:");
  1113. X    unsetmark(CFCUR);
  1114. X    if(c < RV_NUL)
  1115. X      return(c);
  1116. X    else if(c == RV_NUL)
  1117. X      (void) strcpy(pattern, "*");
  1118. X  }
  1119. X  if(one && ISTAG(cdlist, CFCUR)) {     /* Current file */
  1120. X    untagfile(CFCUR);
  1121. X    unsetmark(CFCUR);
  1122. X  }
  1123. X  else                                  /* Matching files */
  1124. X    for(f = 0; f < CNFIL; f++)
  1125. X      if(umatch(cdlist, f, pattern) > 0 && ISTAG(cdlist, f)) {
  1126. X       untagfile(f);
  1127. X       unsetmark(f);
  1128. X      }
  1129. X
  1130. X  return(RV_OK);
  1131. X
  1132. X} /* untag() */
  1133. X
  1134. X/*
  1135. X *      EXECUTE CURRENT FILE
  1136. X */
  1137. X
  1138. X/* Check if current file is given in command */
  1139. LOCAL int filemissing(s)
  1140. X  register char *s;
  1141. X{
  1142. X  while(*s) {
  1143. X    if(*s == '%') {             /* Leadin found */
  1144. X      ++s;
  1145. X      if(*s == 'f' || *s == 'F' || *s == 'p' || *s == 'P')
  1146. X       return(0);              /* Found */
  1147. X    }
  1148. X    else
  1149. X      ++s;
  1150. X  }
  1151. X  return(1);
  1152. X
  1153. X} /* filemissing() */
  1154. X
  1155. X/* Execute or execute on file f */
  1156. LOCAL int execfile(f, m)
  1157. X  register int f, m;
  1158. X{
  1159. X  char cmd[EXECLEN], buf[2*INPLEN], par[INPLEN];
  1160. X  register xlist *xp;
  1161. X  register int c;
  1162. X
  1163. X  if(m)
  1164. X    setmark(f, FF_MARK);
  1165. X  /* Check if a command is defined for filetype */
  1166. X  for(xp = xroot; xp; xp = (xlist *) XNEXT(xp))
  1167. X    if(umatch(cdlist, f, XTYPE(xp)))
  1168. X      break;
  1169. X
  1170. X  /* Execute filetype dependent command if defined */
  1171. X  if(xp && XCOMD(xp))  {
  1172. X    if(XCOMM(xp))
  1173. X      puthelp("%s: %s #%s", who, FFNAM(cdlist, f), XCOMM(xp));
  1174. X    else
  1175. X      puthelp("%s: %s", who, FFNAM(cdlist, f));
  1176. X    c = putecho("Execute:");
  1177. X    c = getline(buf, sizeof(buf), c, 'l', XCOMD(xp), GNULL, 0);
  1178. X    if(m)
  1179. X      unsetmark(f);
  1180. X    if(c != RV_OK)
  1181. X      return(c);
  1182. X    if(filemissing(buf))
  1183. X      (void) sprintf(buf, "%s %%F", buf);
  1184. X  }
  1185. X  /* File is executable */
  1186. X  else if(FMODE(cdlist, f) == FF_EXEC) {
  1187. X    puthelp("%s: Give parameter(s) or a command", who);
  1188. X    c = putecho("Execute %s:", FFNAM(cdlist, f));
  1189. X    c = getline(par, sizeof(par), c, 'l', NULL, GNULL, 0);
  1190. X    if(m)
  1191. X      unsetmark(f);
  1192. X    if(c < RV_NUL)
  1193. X      return(c);
  1194. X    else if(c == RV_NUL)
  1195. X      (void) strcpy(buf, "./%F");
  1196. X    else if(filemissing(par))
  1197. X      (void) sprintf(buf, "%%F %s", par);
  1198. X    else
  1199. X      (void) strcpy(buf, par);
  1200. X  }
  1201. X  /* Execute command on current file */
  1202. X  else {
  1203. X    puthelp("%s: Give a command and parameter(s)", who);
  1204. X    c = putecho("Execute on %s:", FFNAM(cdlist, f));
  1205. X    c = getline(par, sizeof(par), c, 'l', NULL, GNULL, 0);
  1206. X    if(m)
  1207. X      unsetmark(f);
  1208. X    if(c != RV_OK)
  1209. X      return(c);
  1210. X    if(filemissing(par))
  1211. X      (void) sprintf(buf, "%s %%F", par);
  1212. X    else
  1213. X      (void) strcpy(buf, par);
  1214. X  }
  1215. X
  1216. X  /* Format command line and execute */
  1217. X  c = userformat(cmd, buf, V_FC1, "EXECUTE");
  1218. X  if(c == RV_NUL) {
  1219. X    puthelp("%s %s", who, hitkey);
  1220. X    return(errequest(FFNAM(cdlist, f), "Bad format"));
  1221. X  }
  1222. X  else if(c < RV_NUL)
  1223. X    return(c);
  1224. X
  1225. X  puthelp("%s: %s", who, cmd);
  1226. X  c = callsystem(cmd, 1, 0);
  1227. X
  1228. X  if(c != RV_OK) {
  1229. X    puthelp("%s: %s %s", who, cmd, hitkey);
  1230. X    return(errequest(FFNAM(cdlist, f), "Error in executing"));
  1231. X  }
  1232. X  return(hitakey("Return from execute (Hit a key)", lines-1, DA_REVERSE));
  1233. X
  1234. X} /* execfile() */
  1235. X
  1236. X/* Execute or execute on files */
  1237. LOCAL int execute(one)
  1238. X  register int one;
  1239. X{
  1240. X  register int c, f, m;
  1241. X
  1242. X  if(CNFIL == 0)                /* Nothing to execute */
  1243. X    return(RV_OK);
  1244. X
  1245. X  who = "EXECUTE FILE";
  1246. X  if( !one && CNTAG) {          /* Tagged files */
  1247. X    m = 1;
  1248. X    for(f = 0; f < CNFIL; f++)
  1249. X      if(ISTAG(cdlist, f)) {
  1250. X       untagfile(f);
  1251. X       c = execfile(f, m);
  1252. X       m = 0;
  1253. X       if(c == 'q' || c < RV_NUL)
  1254. X         break;
  1255. X      }
  1256. X  }
  1257. X  else                          /* Current file */
  1258. X    c = execfile(CFCUR, 1);
  1259. X
  1260. X  checkdlist(CPNAM);            /* Directory needs checking */
  1261. X  return(c);
  1262. X
  1263. X} /* execute() */
  1264. X
  1265. X/*
  1266. X *      FILE MENU LOOP
  1267. X */
  1268. X
  1269. X#if     defined(SIGWINCH) && defined(TIOCGWINSZ)
  1270. X/* Refresh file screen after screen size changes */
  1271. GLOBL int refreshfile(f)
  1272. X  register int f;
  1273. X{
  1274. X  if(f)
  1275. X    (void) refreshtree(0);
  1276. X  f = CFCUR;
  1277. X  CFTOP = CFCUR = 0;
  1278. X  while(CFCUR != f && gofile(cdlist, 1))
  1279. X    ;
  1280. X  flast = -1;
  1281. X  fileflag = SF_FULL;
  1282. X  return(RV_OK);
  1283. X
  1284. X} /* refreshfile() */
  1285. X#endif  /* SIGWINCH && TIOCGWINSZ */
  1286. X
  1287. X/* File menu */
  1288. GLOBL int filemenu(f, r)
  1289. X  register int f, r;
  1290. X{
  1291. X  register int c, i, j;
  1292. X
  1293. X  who = "FILE MENU";
  1294. X  /* Change to directory and check if it is empty */
  1295. X  if((c = changelist(cdlist, who)) != RV_OK)
  1296. X    return(c);
  1297. X  else if(r != RV_DIR && CNFIL == 0) {
  1298. X    puthelp("%s: %s (Y:change  ELSE:don't change)", who, CFNAM);
  1299. X    if((c = errequest(CFNAM, "Is empty, change anyway ?")) != 'y')
  1300. X      return(c);
  1301. X  }
  1302. X
  1303. X  /* Position to current file on screen */
  1304. X  if(f >= 0 && f < CNFIL)
  1305. X    while(CFCUR != f)
  1306. X      (void) gofile(cdlist, CFCUR < f ? 1 : -1);
  1307. X
  1308. X  /* Init file variables */
  1309. X  if(menuline == NULL)
  1310. X    menuline = fmline;
  1311. X  buildflag = 0;
  1312. X  nscroll   = 0;
  1313. X  flast     = -1;
  1314. X  fmark     = -1;
  1315. X  fileflag  = SF_FULL;
  1316. X
  1317. X  /* File menu loop */
  1318. X  do {
  1319. X    /* Update file screen if needed and clock */
  1320. X    if(fileflag && !keypressed())
  1321. X      updatefiles();
  1322. X#ifdef  UTCLOCK
  1323. X    if(VARSET(V_CL))
  1324. X      clockon();
  1325. X#endif  /* UTCLOCK */
  1326. X    flushout();
  1327. X    c = getkey();
  1328. X#ifdef  UTCLOCK
  1329. X    if(VARSET(V_CL))
  1330. X      clockoff();
  1331. X#endif  /* UTCLOCK */
  1332. X    switch(c) {
  1333. X      default:                  /* Unknown: ring the bell */
  1334. X       bell(VARSET(V_BL));
  1335. X       break;
  1336. X      case K_BACK:              /* Previous file */
  1337. X      case 'k':                 /* For vi fans */
  1338. X       if( !gofile(cdlist, -1))
  1339. X         bell(VARSET(V_BL));
  1340. X       break;
  1341. X      case K_FORW:              /* Next file */
  1342. X      case 'j':                 /* For vi fans */
  1343. X       if( !gofile(cdlist, 1))
  1344. X         bell(VARSET(V_BL));
  1345. X       break;
  1346. X      case K_PREV:              /* Up file */
  1347. X       if(gofile(cdlist, -1))
  1348. X         for(i = 1; i < fperline; i++)
  1349. X           (void) gofile(cdlist, -1);
  1350. X       else
  1351. X         bell(VARSET(V_BL));
  1352. X       break;
  1353. X      case K_NEXT:              /* Down file */
  1354. X       if(gofile(cdlist, 1))
  1355. X         for(i = 1; i < fperline; i++)
  1356. X           (void) gofile(cdlist, 1);
  1357. X       else
  1358. X         bell(VARSET(V_BL));
  1359. X       break;
  1360. X      case K_PPAG:              /* Previous page */
  1361. X       if(CFTOP > 0 && gofile(cdlist, -1))
  1362. X         for(i = 1; i < fperpage && gofile(cdlist, -1); i++)
  1363. X           ;
  1364. X       else
  1365. X         bell(VARSET(V_BL));
  1366. X       break;
  1367. X      case K_NPAG:              /* Next page */
  1368. X       if((CFTOP + fperpage) < CNFIL && gofile(cdlist, 1))
  1369. X         for(i = 1; i < fperpage && gofile(cdlist, 1); i++)
  1370. X           ;
  1371. X       else
  1372. X         bell(VARSET(V_BL));
  1373. X       break;
  1374. X      case K_HOME:              /* First file */
  1375. X       i = CFCUR;
  1376. X       if(gofile(cdlist, -1)) {
  1377. X         fmark = i;
  1378. X         while(gofile(cdlist, -1))
  1379. X           ;
  1380. X       }
  1381. X       else
  1382. X         bell(VARSET(V_BL));
  1383. X       break;
  1384. X      case K_END:               /* Last file */
  1385. X       i = CFCUR;
  1386. X       if(gofile(cdlist, 1)) {
  1387. X         fmark = i;
  1388. X         while(gofile(cdlist, 1))
  1389. X           ;
  1390. X       }
  1391. X       else
  1392. X         bell(VARSET(V_BL));
  1393. X       break;
  1394. X      case '@':                 /* Mark current file */
  1395. X      case K_MARK:
  1396. X       fmark = CFCUR;
  1397. X       break;
  1398. X      case '#':                 /* Goto previously marked file */
  1399. X      case K_GOTO:
  1400. X       j = fmark;
  1401. X       for(i = CFCUR; i < CNFIL; i++)
  1402. X         if(fmark == i) {
  1403. X           while(gofile(cdlist, 1) && CFCUR != fmark)
  1404. X             ;
  1405. X           fmark = j;
  1406. X           goto MDONE;
  1407. X         }
  1408. X       for(i = 0; i < CFCUR; i++)
  1409. X         if(fmark == i) {
  1410. X           while(gofile(cdlist, -1) && CFCUR != fmark)
  1411. X             ;
  1412. X           fmark = j;
  1413. X           goto MDONE;
  1414. X         }
  1415. X       bell(VARSET(V_BL));
  1416. MDONE:  break;
  1417. X      case K_TAG:               /* Next tagged file */
  1418. X       for(i = CFCUR + 1; i < CNFIL; i++)
  1419. X         if(ISTAG(cdlist, i)) {
  1420. X           while(gofile(cdlist, 1) && CFCUR != i)
  1421. X             ;
  1422. X           goto TDONE;
  1423. X         }
  1424. X       for(i = 0; i < CFCUR; i++)
  1425. X         if(ISTAG(cdlist, i)) {
  1426. X           while(gofile(cdlist, -1) && CFCUR != i)
  1427. X             ;
  1428. X           goto TDONE;
  1429. X         }
  1430. X       bell(VARSET(V_BL));
  1431. TDONE:  break;
  1432. X      case K_UP:                /* Scroll up */
  1433. X       if( !scrollfile(-1))
  1434. X         bell(VARSET(V_BL));
  1435. X       break;
  1436. X      case K_DOWN:              /* Scroll down */
  1437. X       if( !scrollfile(1))
  1438. X         bell(VARSET(V_BL));
  1439. X       break;
  1440. X      case '>':                 /* Change to directory */
  1441. X      case K_INS:
  1442. X       c = gotodirectory();
  1443. X       break;
  1444. X      case '<':                 /* Back to parent directory */
  1445. X      case K_DEL:
  1446. X       c = gotoparent();
  1447. X       break;
  1448. X      case K_SIZE:              /* Screen size changed */
  1449. X#if     defined(SIGWINCH) && defined(TIOCGWINSZ)
  1450. X       c = RV_SIZ;
  1451. X#else   /* !SIGWINCH || !TIOCGWINSZ */
  1452. X       c = RV_OK;
  1453. X#endif  /* SIGWINCH && TIOCGWINSZ */
  1454. X       /*Fall thru*/
  1455. X      case K_REFR:              /* Refresh */
  1456. X       fileflag = SF_FULL;
  1457. X       break;
  1458. X      case 'n':                 /* New sort file list */
  1459. X      case 'N':
  1460. X       fmark = -1;
  1461. X       if((c = sortlist(cdlist, CSORT ? 0 : 1)) == RV_OK)
  1462. X         fileflag |= SF_TREE;
  1463. X       break;
  1464. X      case 'd':                 /* Date */
  1465. X      case 'D':
  1466. X       c = printdate();
  1467. X       break;
  1468. X      case 'w':                 /* Current directory */
  1469. X      case 'W':
  1470. X       c = printcwd();
  1471. X       break;
  1472. X      case '?':                 /* Help */
  1473. X      case 'H':
  1474. X      case 'h':
  1475. X      case K_HELP:
  1476. X       c = showhelp('f');
  1477. X       break;
  1478. X      case 't':                 /* Tag current or tagged file(s) */
  1479. X      case 'T':
  1480. X       c = tag(CUR(c));
  1481. X       break;
  1482. X      case 'u':                 /* Untag current or tagged file(s) */
  1483. X      case 'U':
  1484. X       c = untag(CUR(c));
  1485. X       break;
  1486. X      case 'g':                 /* Search string in file */
  1487. X      case 'G':
  1488. X       c = grep(CUR(c));
  1489. X       break;
  1490. X      case 'f':                 /* Find file */
  1491. X      case 'F':
  1492. X       c = find(CUR(c));
  1493. X       break;
  1494. X      case 'c':                 /* Copy current or tagged file(s) */
  1495. X      case 'C':
  1496. X       c = copy(CUR(c));
  1497. X       break;
  1498. X      case 'e':                 /* Edit current or tagged file(s) */
  1499. X      case 'E':
  1500. X       c = edit(CUR(c));
  1501. X       break;
  1502. X      case 's':                 /* Status of current or tagged file(s) */
  1503. X      case 'S':
  1504. X       c = status(CUR(c), 1);
  1505. X       break;
  1506. X      case 'i':                 /* Short info of current or tagged file(s) */
  1507. X      case 'I':
  1508. X       c = status(CUR(c), 0);
  1509. X       break;
  1510. X      case 'p':                 /* Print current or tagged file(s) */
  1511. X      case 'P':
  1512. X       c = print(CUR(c));
  1513. X       break;
  1514. X      case 'v':                 /* View current or tagged file(s) */
  1515. X      case 'V':
  1516. X       c = view(CUR(c));
  1517. X       break;
  1518. X      case 'm':                 /* Move current or tagged file(s) */
  1519. X      case 'M':
  1520. X       c = move(CUR(c));
  1521. X       break;
  1522. X      case 'r':                 /* Remove current or tagged file(s) */
  1523. X      case 'R':
  1524. X       c = remove(CUR(c));
  1525. X       break;
  1526. X      case 'l':                 /* List files */
  1527. X      case 'L':
  1528. X       c = list(CUR(c));
  1529. X       break;
  1530. X      case 'x':                 /* Execute current file */
  1531. X      case 'X':
  1532. X       c = execute(CUR(c));
  1533. X       break;
  1534. X      case '0':                 /* Switch menu line */
  1535. X       menuline = menuline == ufilemenu ? fmline : ufilemenu;
  1536. X       fileflag |= SF_HELP;
  1537. X       break;
  1538. X      case '1':                 /* User defined file commands 1..9 */
  1539. X      case '2':
  1540. X      case '3':
  1541. X      case '4':
  1542. X      case '5':
  1543. X      case '6':
  1544. X      case '7':
  1545. X      case '8':
  1546. X      case '9':
  1547. X       c = usercommand(c - '0' + V_FC0);
  1548. X       break;
  1549. X      case '!':                 /* Shell escape */
  1550. X      case '$':
  1551. X       c = history(c, V_FC1);
  1552. X       if(VARSET(V_ST))
  1553. X         (void) scandlist(droot);
  1554. X       break;
  1555. X      case '=':                 /* Show/set variables */
  1556. X       c = variables();
  1557. X       break;
  1558. X      case ':':                 /* Show/set file type commands */
  1559. X       c = commands();
  1560. X       break;
  1561. X      case '|':                 /* Show key bindings */
  1562. X       c = bindings();
  1563. X       break;
  1564. X      case '/':                 /* Rebuild file list */
  1565. X       fmark = -1;
  1566. X       CFLAG = FL_CHG;
  1567. X       ++buildflag;
  1568. X       c = RV_OK;
  1569. X       break;
  1570. X      case 'z':                 /* Zoom file list */
  1571. X      case 'Z':
  1572. X       c = zoomfile();
  1573. X       break;
  1574. X      case 'a':                 /* Display version string */
  1575. X      case 'A':
  1576. X       c = putversion(echoline, "ABOUT: Utree version");
  1577. X       break;
  1578. X      case 'q':                 /* Return to tree screen */
  1579. X      case 'Q':
  1580. X      case ' ':
  1581. X      case K_SEL:
  1582. X      case K_BRK:
  1583. X       c = RV_RET;
  1584. X       break;
  1585. X      case K_EOF:               /* Exit */
  1586. X       c = RV_END;
  1587. X       break;
  1588. X    }
  1589. X#if     defined(SIGWINCH) && defined(TIOCGWINSZ)
  1590. X    /* Refresh screen after screen resize */
  1591. X    if(c == RV_SIZ)
  1592. X      c = refreshfile(1);
  1593. X#endif  /* SIGWINCH && TIOCGWINSZ */
  1594. X    /* Rebuilding needed */
  1595. X    if(buildflag && updatedlist() != RV_OK)
  1596. X      c = RV_ERR;
  1597. X  } while(c >= RV_INT);
  1598. X
  1599. X  /* Set treeflag and return */
  1600. X  treeflag = SF_FULL;
  1601. X  return(c);
  1602. X
  1603. X} /* filemenu() */
  1604. X
  1605. END_OF_FILE
  1606. if test 41484 -ne `wc -c <'src/file.c'`; then
  1607.     echo shar: \"'src/file.c'\" unpacked with wrong size!
  1608. fi
  1609. # end of 'src/file.c'
  1610. fi
  1611. if test -f 'src/term.c' -a "${1}" != "-c" ; then 
  1612.   echo shar: Will not clobber existing file \"'src/term.c'\"
  1613. else
  1614. echo shar: Extracting \"'src/term.c'\" \(30770 characters\)
  1615. sed "s/^X//" >'src/term.c' <<'END_OF_FILE'
  1616. X/*
  1617. X *      TERM.C
  1618. X *      UTREE terminal, screen and keyboard routines.
  1619. X *      3.01-um klin, Wed May  1 14:21:09 1991
  1620. X *              klin, Mon Oct  7 15:16:22 1991, Bug in putchar() deleted
  1621. X *              klin, Sat Oct 26 15:26:07 1991, Marking directories changed
  1622. X *      3.02-um klin, Fri Nov  1 10:44:45 1991, Screen layout changed
  1623. X *                    Sun Nov 10 19:46:21 1991, Function key handling changed
  1624. X *                    Sun Nov 24 12:22:56 1991, Extensions for XENIX reported
  1625. X *                                              by Rolf Gebhardt (RG 11/22/91)
  1626. X *                                              Bug fixes in output reported by
  1627. X *                                              Reinhard Wobst and Rolf Gebhardt
  1628. X *                                              Video attributes changed
  1629. X *      3.03-um klin, Tue Feb 11 19:39:09 1992, Video handling changed
  1630. X *                                              Handle glitch capabilities
  1631. X *                                              properly
  1632. X *              klin, Sun Feb 23 20:33:30 1992, Key handling and key bindings
  1633. X *                                              changed. getkey() changed for
  1634. X *                                              handling key bindings from
  1635. X *                                              key bindings list
  1636. X *            a klin, Sun Mar 15 19:08:25 1992, Bug fix in getkey(), clearline()
  1637. X *                                              and cleartoend().
  1638. X *                                              Minor changes for AIX 3.2
  1639. X *
  1640. X *      Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen.
  1641. X *      For copying and distribution information see the file COPYRIGHT.
  1642. X */
  1643. X#ifndef lint
  1644. static char sccsid[] = "@(#) utree 3.03a-um (klin) Mrz 15 1992 term.c";
  1645. X#endif  /* !lint */
  1646. X
  1647. X#include "defs.h"
  1648. X
  1649. X/*      TEST:   Handling of sg/ug glitches (i.e. for bando terminal)
  1650. X *      Handling of sg/ug glitches may be wrong because i could test
  1651. X *      their handling on xterm simulating the sg/ug glitches only.
  1652. X */
  1653. X
  1654. X/* ---- Local/global variables and definitions ------------------------ */
  1655. X
  1656. X#define TCAPLEN 1024            /* Length of termcap buffers            */
  1657. X#define KBUFLEN 254             /* Length of keyboard buffer            */
  1658. X#define HUGE    9999            /* A huge number                        */
  1659. X
  1660. GLOBL char PC;                  /* Needed by termcap (???)              */
  1661. GLOBL char *UP;                 /* Needed by termcap (???)              */
  1662. GLOBL char *BC;                 /* Needed by termcap (???)              */
  1663. X
  1664. LOCAL int _XR;                  /* Carriage return glitch               */
  1665. LOCAL int _MS;                  /* Can move cursor in standout mode     */
  1666. LOCAL int _SG;                  /* Standout mode glitch: # of blanks    */
  1667. LOCAL int _UG;                  /* Underline glitch: # of blanks        */
  1668. LOCAL char *_CM;                /* Cursor motion                        */
  1669. LOCAL char *_CL;                /* Clear screen                         */
  1670. LOCAL char *_CD;                /* Clear to end of screen               */
  1671. LOCAL char *_CE;                /* Clear to end of line                 */
  1672. LOCAL char *_TI;                /* Init string for cursor motion        */
  1673. LOCAL char *_TE;                /* Exit string for cursor motion        */
  1674. LOCAL char *_KS;                /* Turn on keypad transmit mode         */
  1675. LOCAL char *_KE;                /* Turn off keypad transmit mode        */
  1676. LOCAL char *_MR;                /* Turn on reverse video mode           */
  1677. LOCAL char *_MB;                /* Turn on blink video mode             */
  1678. LOCAL char *_MD;                /* Turn on bold video mode              */
  1679. LOCAL char *_MH;                /* Turn on half bright video mode       */
  1680. LOCAL char *_ME;                /* Turn off all video attributes        */
  1681. LOCAL char *_US;                /* Start underlining                    */
  1682. LOCAL char *_UE;                /* End underlining                      */
  1683. LOCAL char *_IC;                /* Insert character at cursor position  */
  1684. LOCAL char *_DC;                /* Delete character at cursor position  */
  1685. LOCAL char *_AL;                /* Insert line above line cursor is on  */
  1686. LOCAL char *_DL;                /* Delete line cursor is on             */
  1687. LOCAL char *_CS;                /* Set scroll region                    */
  1688. LOCAL char *_NL;                /* New line (default: ^J = NL)          */
  1689. LOCAL char *_CR;                /* Carriage return (default: ^M = CR)   */
  1690. LOCAL char *_LE;                /* Cursor left (default: ^H = BS)       */
  1691. LOCAL char *_DO;                /* Cursor down                          */
  1692. LOCAL char *_SF;                /* Scroll screen up                     */
  1693. LOCAL char *_SR;                /* Scroll screen down                   */
  1694. LOCAL char *_SC;                /* Save cursor position                 */
  1695. LOCAL char *_RC;                /* Restore cursor position              */
  1696. LOCAL char *_VE;                /* Cursor normal                        */
  1697. LOCAL char *_VS;                /* Cursor very visible                  */
  1698. LOCAL char *_VI;                /* Cursor invisible                     */
  1699. LOCAL char *_BL;                /* Bell (default ^G = BEL)              */
  1700. LOCAL char *_AC = NULL;         /* Alternate character set              */
  1701. LOCAL char *_EA = NULL;         /* Enable alternate character set       */
  1702. LOCAL char *_AS = NULL;         /* Alternate character set on           */
  1703. LOCAL char *_AE = NULL;         /* Alternate character set off          */
  1704. X#ifdef  XENIX   /* RG 11/22/91 */
  1705. LOCAL char *_G2 = NULL;         /* Upper left corner                    */
  1706. LOCAL char *_GH = NULL;         /* Horizontal bar                       */
  1707. LOCAL char *_G1 = NULL;         /* Upper right corner                   */
  1708. LOCAL char *_GV = NULL;         /* Vertical bar                         */
  1709. LOCAL char *_G4 = NULL;         /* Lower right corner                   */
  1710. LOCAL char *_G3 = NULL;         /* Lower left corner                    */
  1711. LOCAL char *_GD = NULL;         /* Top tee                              */
  1712. LOCAL char *_GL = NULL;         /* Right tee                            */
  1713. LOCAL char *_GU = NULL;         /* Bottom tee                           */
  1714. LOCAL char *_GR = NULL;         /* Left tee                             */
  1715. LOCAL char *_GC = NULL;         /* Plus sign = mark sign                */
  1716. X#endif  /* XENIX */
  1717. X
  1718. LOCAL char termbuf[TCAPLEN];    /* Termcap buffer                       */
  1719. LOCAL int nfkeys;               /* Number of defined function keys      */
  1720. X#ifdef BSD
  1721. LOCAL struct sgttyb raw, tty;   /* Terminal driver data record          */
  1722. X# define TCGETA TIOCGETP
  1723. X# define TCSETA TIOCSETP
  1724. X#else   /* SYSV */
  1725. LOCAL struct termio raw, tty;
  1726. X# ifndef HASFIONREAD
  1727. LOCAL int kbflag;               /* Input mode flag                      */
  1728. X# endif /* !HASFIONREAD */
  1729. X#endif  /* BSD */
  1730. X
  1731. LOCAL kchar kbuf[KBUFLEN+2];    /* Input buffer                         */
  1732. LOCAL int kcnt = 0;             /* Input buffer counter                 */
  1733. LOCAL int kind = 0;             /* Input buffer index                   */
  1734. LOCAL int curx = HUGE;          /* Current screen column                */
  1735. LOCAL int cury = HUGE;          /* Current screen line                  */
  1736. LOCAL int vatt = VA_NORMAL;     /* Current video attributes setting     */
  1737. LOCAL int gatt = GC_OFF;        /* Current graphic character set flag   */
  1738. X
  1739. X/* ---- External variables and functions ------------------------------ */
  1740. X
  1741. X#ifdef  BSD
  1742. XEXTRN short ospeed;             /* Is ospeed really needed???           */
  1743. X#endif  /* BSD */
  1744. XEXTRN char *getenv();
  1745. XEXTRN char *tgetstr();
  1746. XEXTRN char *tgoto();
  1747. X
  1748. X/* ---- Local/global functions and procedures ------------------------- */
  1749. X
  1750. X/*
  1751. X *      INTERNAL USED ROUTINES
  1752. X */
  1753. X
  1754. X/* Output one character for tputs() */
  1755. LOCAL int _putch(c)
  1756. X  register int c;
  1757. X{
  1758. X  return(putc((unsigned char) c, stdout));
  1759. X
  1760. X} /* _putch() */
  1761. X
  1762. X/*TEST: Handling of sg/ug glitches */
  1763. X/* Move cursor back for terminals with underline or standout glitch */
  1764. LOCAL VOID _backglitch(j)
  1765. X  register int j;
  1766. X{
  1767. X  register int i;
  1768. X
  1769. X  for(i = 0; i < j; i++) {
  1770. X    if(_LE)
  1771. X      tputs(_LE, 1, _putch);
  1772. X    else if(BC)
  1773. X      tputs(BC, 1, _putch);
  1774. X    else
  1775. X      (void) _putch('\b');
  1776. X  }
  1777. X
  1778. X} /* _backglitch() */
  1779. X
  1780. X/*
  1781. X *      VIDEO ATTRIBUTE AND GRAPHIC CHARSET ROUTINES
  1782. X */
  1783. X
  1784. X/* Turn on/off video attributes as defined in mask v */
  1785. GLOBL VOID videoset(v)
  1786. X  register int v;
  1787. X{
  1788. X  if(vatt) {                            /* Video attributes off */
  1789. X    if((vatt & VA_UNDERLINE) && _UE) {
  1790. X      tputs(_UE, 1, _putch);
  1791. X/*TEST: Handling of sg/ug glitches */
  1792. X      if(_UG > 0)
  1793. X       _backglitch(_UG);
  1794. X      vatt &= ~VA_UNDERLINE;
  1795. X    }
  1796. X    if(vatt && _ME) {
  1797. X      tputs(_ME, 1, _putch);
  1798. X/*TEST: Handling of sg/ug glitches */
  1799. X      if(_SG > 0)
  1800. X       _backglitch(_SG);
  1801. X    }
  1802. X  }
  1803. X  vatt = VA_NORMAL;
  1804. X  if(v & VA_REVERSE && _MR) {           /* Video reverse */
  1805. X    tputs(_MR, 1, _putch);
  1806. X/*TEST: Handling of sg/ug glitches */
  1807. X    if(_SG > 0)
  1808. X      _backglitch(_SG);
  1809. X    vatt |= VA_REVERSE;
  1810. X  }
  1811. X  if(v & VA_UNDERLINE && _US) {         /* Start underlining */
  1812. X    tputs(_US, 1, _putch);
  1813. X/*TEST: Handling of sg/ug glitches */
  1814. X    if(_UG > 0)
  1815. X      _backglitch(_UG);
  1816. X    vatt |= VA_UNDERLINE;
  1817. X  }
  1818. X  if(v & VA_BLINK && _MB) {             /* Video blink */
  1819. X    tputs(_MB, 1, _putch);
  1820. X    vatt |= VA_BLINK;
  1821. X  }
  1822. X  if(v & VA_BOLD && _MD) {              /* Video bold */
  1823. X    tputs(_MD, 1, _putch);
  1824. X    vatt |= VA_BOLD;
  1825. X  }
  1826. X  if(v & VA_HALF && _MH) {              /* Video half bright */
  1827. X    tputs(_MH, 1, _putch);
  1828. X    vatt |= VA_HALF;
  1829. X  }
  1830. X
  1831. X} /* videoset() */
  1832. X
  1833. X/* Turn on/off graphic character set as defined in flag f */
  1834. GLOBL VOID graphicset(f)
  1835. X  register int f;
  1836. X{
  1837. X  if(gatt != f) {
  1838. X    if(f && _AS)                /* Enable graphic charset */
  1839. X      tputs(_AS, 1, _putch);
  1840. X    else if(_AE)                /* Disable graphic charset */
  1841. X      tputs(_AE, 1, _putch);
  1842. X    gatt = f;
  1843. X  }
  1844. X
  1845. X} /* graphicset() */
  1846. X
  1847. X/*
  1848. X *      OUTPUT ROUTINES
  1849. X */
  1850. X
  1851. X/* Ring the bell */
  1852. GLOBL VOID bell(f)
  1853. X  register int f;
  1854. X{
  1855. X  if(f) {
  1856. X    if(_BL)
  1857. X      tputs(_BL, 1, _putch);
  1858. X    else
  1859. X      (void) _putch(7);
  1860. X  }
  1861. X
  1862. X} /* bell() */
  1863. X
  1864. X/* Move cursor back one character */
  1865. GLOBL VOID backspace()
  1866. X{
  1867. X  if(curx > 0) {
  1868. X    if(_LE)
  1869. X      tputs(_LE, 1, _putch);
  1870. X    else if(BC)
  1871. X      tputs(BC, 1, _putch);
  1872. X    else
  1873. X      (void) _putch('\b');
  1874. X    --curx;
  1875. X  }
  1876. X
  1877. X} /* backspace() */
  1878. X
  1879. X/* Move to beginning of line */
  1880. GLOBL VOID begline()
  1881. X{
  1882. X  if(curx > 0) {
  1883. X    curx = 0;
  1884. X    if(_XR)
  1885. X      (void) cursorxy(0, cury);
  1886. X    else if(_CR)
  1887. X      tputs(_CR, 1, _putch);
  1888. X    else
  1889. X      (void) _putch('\r');
  1890. X  }
  1891. X
  1892. X} /* begline() */
  1893. X
  1894. X/* Move to beginning of next line */
  1895. GLOBL VOID newline()
  1896. X{
  1897. X  if(cury < lines) {
  1898. X    begline();
  1899. X    ++cury;
  1900. X    if(_NL)
  1901. X      tputs(_NL, 1, _putch);
  1902. X    else if(_DO)
  1903. X      tputs(_DO, 1, _putch);
  1904. X    else
  1905. X      (void) _putch('\n');
  1906. X  }
  1907. X
  1908. X} /* newline() */
  1909. X
  1910. X/* Write character c if cursor is on screen */
  1911. GLOBL int putchar(c)
  1912. X  register int c;
  1913. X{
  1914. X  if(videoattr != vatt)         /* Check and set video attributes */
  1915. X    videoset(videoattr);
  1916. X  if(graphattr != gatt)         /* Check and set graphic charset */
  1917. X    graphicset(graphattr);
  1918. X  switch(c) {
  1919. X    case 7:                     /* Bell */
  1920. X      bell(1);
  1921. X      break;
  1922. X    case '\b':                  /* Backspace */
  1923. X      backspace();
  1924. X      break;
  1925. X    case '\t':                  /* Tab */
  1926. X      if(curx < columns && cury < lines) {
  1927. X       do
  1928. X         (void) _putch(' ');
  1929. X       while(++curx % 8 && curx < columns);
  1930. X      }
  1931. X      break;
  1932. X    case '\n':                  /* Newline */
  1933. X      newline();
  1934. X      break;
  1935. X    case '\r':                  /* Carriage return */
  1936. X      begline();
  1937. X      break;
  1938. X    default:                    /* Others */
  1939. X      if(curx < columns && cury < lines && isprint(c & 0x7f)) {
  1940. X       (void) _putch(c);
  1941. X       ++curx;
  1942. X      }
  1943. X      break;
  1944. X  }
  1945. X  return(curx < columns && cury < lines ? 1 : 0);
  1946. X
  1947. X} /* putchar() */
  1948. X
  1949. X/* Flush output buffer */
  1950. GLOBL VOID flushout()
  1951. X{
  1952. X  (void) fflush(stdout);
  1953. X
  1954. X} /* flushout() */
  1955. X
  1956. X/*
  1957. X *      INPUT ROUTINES
  1958. X */
  1959. X
  1960. X/* Read one character from keyboard. Ignore or handle signals */
  1961. GLOBL int getchar()
  1962. X{
  1963. X  register int c;
  1964. X
  1965. X#ifdef  BSD
  1966. X  atread = 1;
  1967. X# if    defined(SIGWINCH) && defined(TIOCGWINSZ)
  1968. X  /* BSD: Signal SIGWINCH doesn't interrupt systemcall read() ! */
  1969. X  /*      Set up here if SIGWINCH is catched and return K_SIZE  */
  1970. X  if(setjmp(winchjump) && sizechange) {
  1971. X    sizechange = atread = 0;
  1972. X    return(K_SIZE);
  1973. X  }
  1974. X# endif /* SIGWINCH && TIOCGWINSZ */
  1975. X  c = getc(stdin);
  1976. X  atread = 0;
  1977. X  return(c);
  1978. X#else   /* SYSV */
  1979. X  do {
  1980. X    c = getc(stdin);
  1981. X# if    defined(SIGWINCH) && defined(TIOCGWINSZ)
  1982. X    /* SYSV: Signal SIGWINCH interrupts systemcall read() ! */
  1983. X    /*       So return K_SIZE if signal SIGWINCH is catched */
  1984. X    if(c < 0 && sizechange) {
  1985. X      sizechange = 0;
  1986. X      return(K_SIZE);
  1987. X    }
  1988. X# endif /* SIGWINCH && TIOCGWINSZ */
  1989. X  }
  1990. X  while(c < 0 && errno == EINTR);
  1991. X  return(c);
  1992. X#endif  /* BSD */
  1993. X
  1994. X} /* getchar() */
  1995. X
  1996. X/* Check if input from keyboard is pending */
  1997. GLOBL int keypressed()
  1998. X{
  1999. X  int c;
  2000. X
  2001. X#if     defined(BSD) || defined(HASFIONREAD)
  2002. X  /* Quick check how many chars are to read */
  2003. X  return(ioctl(fileno(stdin), FIONREAD, &c) < 0 ? 0 : c);
  2004. X#else   /* SYSV && !HASFIONREAD */
  2005. X  /* Set stdin to no delay and try to read one char */
  2006. X  (void) fcntl(fileno(stdin), F_SETFL, kbflag|O_NDELAY);
  2007. X  c = getc(stdin);
  2008. X  (void) fcntl(fileno(stdin), F_SETFL, kbflag);
  2009. X  if(c >= 0) {
  2010. X    (void) ungetc(c, stdin);
  2011. X    return(1);
  2012. X  }
  2013. X  return(0);
  2014. X#endif  /* BSD || HASFIONREAD */
  2015. X
  2016. X} /* keypressed() */
  2017. X
  2018. X/* Read a character from keyboard with respect to function keys */
  2019. GLOBL int getkey()
  2020. X{
  2021. X  register klist *fp, *lp, *p;
  2022. X  register kchar c;
  2023. X  register int k;
  2024. X
  2025. X  /* Flush output buffer */
  2026. X  flushout();
  2027. X
  2028. X  /* Input buffer contains character(s) */
  2029. X  if(kcnt > 0) {
  2030. X    --kcnt;
  2031. X    return((int) kbuf[kind++]);
  2032. X  }
  2033. X
  2034. X  /* Get next character */
  2035. X  if((c = getchar()) == 0)      /* Map ASCII-NUL */
  2036. X    c = 0200;
  2037. X  /* Search for first matching entry in key binding list */
  2038. X  for(fp = kroot; fp; fp = (klist *) KBNXT(fp))
  2039. X    if(KBCHR(fp, 0) == c)
  2040. X      break;
  2041. X  /* No match: return character */
  2042. X  if(fp == KNULL)
  2043. X    return((int) c);
  2044. X
  2045. X  /* Search for last matching entry in key binding list */
  2046. X  lp = fp;
  2047. X  while((p = (klist *) KBNXT(lp)) && KBCHR(p, 0) == c)
  2048. X    lp = p;
  2049. X
  2050. X  /* Continue comparison of input and key strings */
  2051. X  for(k = 1; ; k++) {
  2052. X    /* Match: return bound key symbol */
  2053. X    if(fp == lp && KBCHR(fp, k) == 0) {
  2054. X      kcnt = 0;
  2055. X      if(KBSYM(fp) == K_STR && KBINS(fp)) {
  2056. X       kind = 0;
  2057. X       (void) ungetstring(KBINS(fp));
  2058. X       break;
  2059. X      }
  2060. X      return(KBSYM(fp));
  2061. X    }
  2062. X    /* Else: get next character */
  2063. X    if((c = getchar()) == 0)    /* Map ASCII-NUL */
  2064. X      c = 0200;
  2065. X    kbuf[kcnt++] = c;
  2066. X    /* Search for next first and last matching entries in binding list */
  2067. X    while(KBCHR(fp, k) != c && fp != lp)
  2068. X      fp = (klist *) KBNXT(fp);
  2069. X    while(KBCHR(lp, k) != c && lp != fp)
  2070. X      lp = (klist *) KBPRV(lp);
  2071. X    /* No match: exit loop */
  2072. X    if(KBCHR(fp, k) != c)
  2073. X      break;
  2074. X  }
  2075. X
  2076. X  /* No match: return character from input buffer */
  2077. X  --kcnt;
  2078. X  return((int) kbuf[kind++]);
  2079. X
  2080. X} /* getkey() */
  2081. X
  2082. X/* Put back character c into input buffer */
  2083. GLOBL VOID ungetkey(c)
  2084. X  register int c;
  2085. X{
  2086. X  if(kcnt < KBUFLEN)
  2087. X    kbuf[kcnt++] = (kchar) c;
  2088. X
  2089. X} /* ungetkey() */
  2090. X
  2091. X/* Put back string s into input buffer */
  2092. GLOBL int ungetstring(s)
  2093. X  register char *s;
  2094. X{
  2095. X  register int c;
  2096. X
  2097. X  while(*s) {
  2098. X    if(*s == '\\')
  2099. X      switch(*++s) {
  2100. X       default:                        /* Error */
  2101. X         return(1);
  2102. X       case 'b':                       /* Backspace ?? */
  2103. X         c = '\b';
  2104. X         break;
  2105. X       case 'f':                       /* Formfeed  ?? */
  2106. X         c = '\f';
  2107. X         break;
  2108. X       case 'r':                       /* Carriage return */
  2109. X       case 'n':                       /* Newline */
  2110. X         c = '\n';
  2111. X         break;
  2112. X       case 't':                       /* Tab */
  2113. X         c = '\t';
  2114. X         break;
  2115. X       case 's':                       /* Space */
  2116. X         c = ' ';
  2117. X         break;
  2118. X       case 'e':                       /* Escape */
  2119. X       case 'E':
  2120. X         c = 0x1b;
  2121. X         break;
  2122. X      }
  2123. X    else if(*s == '^') {                /* Control chars ?? */
  2124. X      ++s;
  2125. X      if(*s == '?')                     /* DEL */
  2126. X       c = 0x7f;
  2127. X      else if(*s >= '@' && *s <= '_')   /* NUL .. US */
  2128. X       c = *s - '@';
  2129. X      else if(*s >= 'a' && *s <= 'z')   /* SOH .. SUB */
  2130. X       c = *s - '`';
  2131. X      else
  2132. X       return(1);
  2133. X    }
  2134. X    else
  2135. X      c = *s;
  2136. X    ungetkey(c);
  2137. X    ++s;
  2138. X  }
  2139. X  return(0);
  2140. X
  2141. X} /* ungetstring() */
  2142. X
  2143. X/*
  2144. X *      GLOBAL SCREEN ROUTINES
  2145. X */
  2146. X
  2147. X/* Move the cursor to new x,y position */
  2148. GLOBL int cursorxy(x, y)
  2149. X  register int x, y;
  2150. X{
  2151. X  if(x < 0) x = columns + x;
  2152. X  if(y < 0) y = lines   + y;
  2153. X  if(x < 0 || x >= columns || y < 0 || y >= lines) {
  2154. X    curx = cury = HUGE;
  2155. X    return(0);
  2156. X  }
  2157. X  if( !_MS && vatt)             /* Reset video attributes */
  2158. X    videoset(VA_NORMAL);
  2159. X  if(gatt)                      /* Reset graphic charset */
  2160. X    graphicset(GC_OFF);
  2161. X  tputs(tgoto(_CM, x, y), 1, _putch);
  2162. X  curx = x;
  2163. X  cury = y;
  2164. X  return(1);
  2165. X
  2166. X} /* cursorxy() */
  2167. X
  2168. X/* Return current cursor position */
  2169. GLOBL VOID cursorpos(x, y)
  2170. X  register int *x, *y;
  2171. X{
  2172. X  *x = curx;
  2173. X  *y = cury;
  2174. X
  2175. X} /* cursorpos() */
  2176. X
  2177. X/* Insert character at cursor position */
  2178. GLOBL int insertchar()
  2179. X{
  2180. X  if(_IC) {
  2181. X    tputs(_IC, 1, _putch);
  2182. X    return(1);
  2183. X  }
  2184. X  return(0);
  2185. X
  2186. X} /* insertchar() */
  2187. X
  2188. X/* Delete character under cursor */
  2189. GLOBL int deletechar()
  2190. X{
  2191. X  if(_DC) {
  2192. X    tputs(_DC, 1, _putch);
  2193. X    return(1);
  2194. X  }
  2195. X  return(0);
  2196. X
  2197. X} /* deletechar() */
  2198. X
  2199. X/* Insert n lines above line cursor is on */
  2200. GLOBL int insertline(y, n)
  2201. X  register int y, n;
  2202. X{
  2203. X  if(_AL && cursorxy(0, y)) {
  2204. X    while(n--)
  2205. X      tputs(_AL, 1, _putch);
  2206. X    return(1);
  2207. X  }
  2208. X  return(0);
  2209. X
  2210. X} /* insertline() */
  2211. X
  2212. X/* Delete n lines cursor is on */
  2213. GLOBL int deleteline(y, n)
  2214. X  register int y, n;
  2215. X{
  2216. X  if(_DL && cursorxy(0, y)) {
  2217. X    while(n--)
  2218. X      tputs(_DL, 1, _putch);
  2219. X    return(1);
  2220. X  }
  2221. X  return(0);
  2222. X
  2223. X} /* deleteline() */
  2224. X
  2225. X/* Set scroll window from line f to line t */
  2226. GLOBL int windowset(f, t)
  2227. X  register int f, t;
  2228. X{
  2229. X  /* Set scroll region from line f to line t */
  2230. X  if(_CS && f <= t) {
  2231. X    tputs(tgoto(_CS, t, f), t - f + 1, _putch);
  2232. X    return(1);
  2233. X  }
  2234. X  return(0);
  2235. X
  2236. X} /* windowset() */
  2237. X
  2238. X/* Scroll n lines up window from line f to line t */
  2239. GLOBL int windowup(f, t, n)
  2240. X  register int f, t, n;
  2241. X{
  2242. X  /* Set scrollregion from f to t and scroll up n lines */
  2243. X  if(_SF && windowset(f, t)) {
  2244. X    (void) cursorxy(0, t);
  2245. X    while(n-- > 0)
  2246. X      tputs(_SF, lines, _putch);
  2247. X    /* Reset scroll region to screen */
  2248. X    (void) windowset(0, lines - 1);
  2249. X    return(1);
  2250. X  }
  2251. X  /* Scroll up with a combination of insert and delete line */
  2252. X  else if(_AL && deleteline(f, n)) {
  2253. X    (void) insertline(t - n + 1, n);
  2254. X    return(1);
  2255. X  }
  2256. X  return(0);
  2257. X
  2258. X} /* windowup() */
  2259. X
  2260. X/* Scroll n lines down in window from line f to line t */
  2261. GLOBL int windowdown(f, t, n)
  2262. X  register int f, t, n;
  2263. X{
  2264. X  /* Set scrollregion from f to t and scroll down n lines */
  2265. X  if(_SR && windowset(f, t)) {
  2266. X    (void) cursorxy(0, f);
  2267. X    while(n-- > 0)
  2268. X      tputs(_SR, lines, _putch);
  2269. X    /* Reset scroll region to screen */
  2270. X    (void) windowset(0, lines - 1);
  2271. X    return(1);
  2272. X  }
  2273. X  /* Scroll down with a combination of insert and delete line */
  2274. X  else if(_AL && deleteline(t - n + 1 ,n)) {
  2275. X    (void) insertline(f, n);
  2276. X    return(1);
  2277. X  }
  2278. X  return(0);
  2279. X
  2280. X} /* windowdown() */
  2281. X
  2282. X/* Clear the screen */
  2283. GLOBL VOID clearscreen()
  2284. X{
  2285. X  tputs(_CL, lines, _putch);
  2286. X  curx = cury = 0;
  2287. X
  2288. X} /* clearscreen() */
  2289. X
  2290. X/* Clear from cursor position to end of line */
  2291. GLOBL VOID clearline()
  2292. X{
  2293. X  if( !_MS && vatt)             /* Reset video attributes */
  2294. X    videoset(VA_NORMAL);
  2295. X  if(gatt)                      /* Reset graphic charset */
  2296. X    graphicset(GC_OFF);
  2297. X  tputs(_CE, 1, _putch);
  2298. X
  2299. X} /* clearline() */
  2300. X
  2301. X/* Clear to end of screen */
  2302. GLOBL int cleartoend()
  2303. X{
  2304. X  if( !_MS && vatt)             /* Reset video attributes */
  2305. X    videoset(VA_NORMAL);
  2306. X  if(gatt)                      /* Reset graphic charset */
  2307. X    graphicset(GC_OFF);
  2308. X  if(_CD) {
  2309. X    tputs(_CD, lines, _putch);
  2310. X    return(1);
  2311. X  }
  2312. X  return(0);
  2313. X
  2314. X} /* cleartoend() */
  2315. X
  2316. X/* Clear screen from line f to line t */
  2317. GLOBL VOID clearwindow(f, t)
  2318. X  register int f, t;
  2319. X{
  2320. X  /* Clear one line only */
  2321. X  if(f == t) {
  2322. X    (void) cursorxy(0, f);
  2323. X    tputs(_CE, 1, _putch);
  2324. X  }
  2325. X  /* Try clear to end of screen */
  2326. X  else if(t == lines - 1 && _CD) {
  2327. X    (void) cursorxy(0, f);
  2328. X    tputs(_CD, lines, _putch);
  2329. X  }
  2330. X  /* Try clear by window scrolling */
  2331. X  else if( !windowup(f, t, t - f + 1)) {
  2332. X    /* Clear line by line */
  2333. X    while(f <= t) {
  2334. X      (void) cursorxy(0, f++);
  2335. X      tputs(_CE, 1, _putch);
  2336. X    }
  2337. X    (void) cursorxy(0, f);
  2338. X  }
  2339. X
  2340. X} /* clearwindow() */
  2341. X
  2342. X/* Turn on/off keypad transmit mode if f is set/unset */
  2343. GLOBL VOID keypadxmit(f)
  2344. X  register int f;
  2345. X{
  2346. X  if(f && _KS)                  /* Keypad transmit mode */
  2347. X    tputs(_KS, 1, _putch);
  2348. X  else if(_KE)                  /* Keypad normal mode */
  2349. X    tputs(_KE, 1, _putch);
  2350. X
  2351. X} /* keypadxmit() */
  2352. X
  2353. X/* Do some cursor functions defined in mask c */
  2354. GLOBL VOID cursorset(c)
  2355. X  register int c;
  2356. X{
  2357. X  if(c & CF_SAVE && _SC) {              /* Save cursor */
  2358. X    if(vatt)                            /* Reset video attributes */
  2359. X      videoset(VA_NORMAL);
  2360. X    tputs(_SC, 1, _putch);
  2361. X  }
  2362. X  else if(c & CF_RESTORE && _RC)        /* Restore cursor */
  2363. X    tputs(_RC, 1, _putch);
  2364. X  if(c & CF_VISIBLE && _VE)             /* Cursor visible */
  2365. X    tputs(_VE, 1, _putch);
  2366. X  else if(c & CF_INVISIBLE && _VI)      /* Cursor invisible */
  2367. X    tputs(_VI, 1, _putch);
  2368. X
  2369. X} /* cursorset() */
  2370. X
  2371. X/* Init graphical character set if f is set */
  2372. GLOBL VOID initgraphics(f)
  2373. X  register int f;
  2374. X{
  2375. X  register char *ac;
  2376. X
  2377. X  GC_HB = '-';                  /* Use ascii meta chars as default */
  2378. X  GC_VB = GC_LT = GC_RT = '|';
  2379. X  GC_TT = GC_BT = GC_UL = GC_LL = GC_UR = GC_LR = GC_TG = '+';
  2380. X  graphcap = 0;
  2381. X  if(f && (ac = _AC)) {         /* If f is set and acsc is defined */
  2382. X#ifdef  AIX
  2383. X    GC_UL = *ac ? *ac++ : '+';  /* Upper left corner */
  2384. X    GC_HB = *ac ? *ac++ : '-';  /* Horizontal bar */
  2385. X    GC_UR = *ac ? *ac++ : '+';  /* Upper right corner */
  2386. X    GC_VB = *ac ? *ac++ : '|';  /* Vertical bar */
  2387. X    GC_LR = *ac ? *ac++ : '+';  /* Lower right corner */
  2388. X    GC_LL = *ac ? *ac++ : '+';  /* Lower left corner */
  2389. X    GC_TT = *ac ? *ac++ : '+';  /* Top tee */
  2390. X    GC_RT = *ac ? *ac++ : '|';  /* Right tee */
  2391. X    GC_BT = *ac ? *ac++ : '+';  /* Bottom tee */
  2392. X    GC_LT = *ac ? *ac++ : '|';  /* Left tee */
  2393. X    GC_TG = *ac ? *ac++ : '+';  /* Tag: plus sign */
  2394. X#else   /* !AIX */
  2395. X# ifdef XENIX   /* RG 11/22/91 */
  2396. X    if(*ac == '\0') {
  2397. X      GC_UL = _G2 ? *_G2 : '+'; /* Upper left corner */
  2398. X      GC_HB = _GH ? *_GH : '-'; /* Horizontal bar */
  2399. X      GC_UR = _G1 ? *_G1 : '+'; /* Upper right corner */
  2400. X      GC_VB = _GV ? *_GV : '|'; /* Vertical bar */
  2401. X      GC_LR = _G4 ? *_G4 : '+'; /* Lower right corner */
  2402. X      GC_LL = _G3 ? *_G3 : '+'; /* Lower left corner */
  2403. X      GC_TT = _GD ? *_GD : '+'; /* Top tee */
  2404. X      GC_RT = _GL ? *_GL : '|'; /* Right tee */
  2405. X      GC_BT = _GU ? *_GU : '+'; /* Bottom tee */
  2406. X      GC_LT = _GR ? *_GR : '|'; /* Left tee */
  2407. X      GC_TG = _GC ? *_GC : '+'; /* Tag: plus sign */
  2408. X    }
  2409. X# endif /* XENIX */
  2410. X    do {
  2411. X      switch(*ac) {
  2412. X       default:                /* Skip */
  2413. X         ++ac;
  2414. X       case '\0':              /* End of acsc */
  2415. X         break;
  2416. X       case 'j':               /* Lower right corner */
  2417. X         GC_LR = *++ac ? *ac : '+'; break;
  2418. X       case 'k':               /* Upper right corner */
  2419. X         GC_UR = *++ac ? *ac : '+'; break;
  2420. X       case 'l':               /* Upper left corner */
  2421. X         GC_UL = *++ac ? *ac : '+'; break;
  2422. X       case 'm':               /* Lower left corner */
  2423. X         GC_LL = *++ac ? *ac : '+'; break;
  2424. X       case 'q':               /* Horizontal bar */
  2425. X         GC_HB = *++ac ? *ac : '-'; break;
  2426. X       case 't':               /* Left tee */
  2427. X         GC_LT = *++ac ? *ac : '|'; break;
  2428. X       case 'u':               /* Right tee */
  2429. X         GC_RT = *++ac ? *ac : '|'; break;
  2430. X       case 'v':               /* Bottom tee */
  2431. X         GC_BT = *++ac ? *ac : '+'; break;
  2432. X       case 'w':               /* Top tee */
  2433. X         GC_TT = *++ac ? *ac : '+'; break;
  2434. X       case 'x':               /* Vertical bar */
  2435. X         GC_VB = *++ac ? *ac : '|'; break;
  2436. X       case '`':               /* Tag sign: diamond */
  2437. X         GC_TG = *++ac ? *ac : '+'; break;
  2438. X       case 'n':               /* Alternate tag sign: plus */
  2439. X         if(*++ac && GC_TG == '+')
  2440. X           GC_TG = *ac;
  2441. X         break;
  2442. X      }
  2443. X    } while(*ac && *++ac);
  2444. X#endif  /* AIX */
  2445. X    graphcap = 1;
  2446. X    if(_EA)
  2447. X      tputs(_EA, 1, _putch);
  2448. X  }
  2449. X
  2450. X} /* initgraphics() */
  2451. X
  2452. X/*
  2453. X *      TERMINAL ROUTINES
  2454. X */
  2455. X
  2456. X/* Switch terminal to raw mode */
  2457. GLOBL VOID terminalraw(f)
  2458. X  register int f;
  2459. X{
  2460. X  if(_TI && f)
  2461. X    tputs(_TI, 1, _putch);
  2462. X  curx = cury = HUGE;
  2463. X  keypadxmit(KP_XMIT);
  2464. X  flushout();
  2465. X  (void) ioctl(fileno(stdin), TCSETA, &raw);
  2466. X
  2467. X} /* terminalraw() */
  2468. X
  2469. X/* Reset terminal to initial mode */
  2470. GLOBL VOID terminalreset(f)
  2471. X  register int f;
  2472. X{
  2473. X  if(f && _TE)
  2474. X    tputs(_TE, 1, _putch);
  2475. X  curx = cury = HUGE;
  2476. X  keypadxmit(KP_NORMAL);
  2477. X  videoset(VA_NORMAL);
  2478. X  flushout();
  2479. X  (void) ioctl(fileno(stdin), TCSETA, &tty);
  2480. X
  2481. X} /* terminalreset() */
  2482. X
  2483. X/* Enable signal handling */
  2484. GLOBL VOID enablesignals()
  2485. X{
  2486. X#ifdef BSD
  2487. X  raw.sg_flags &= ~RAW;
  2488. X  raw.sg_flags |= CBREAK;
  2489. X#else   /* SYSV */
  2490. X  raw.c_lflag |= ISIG;
  2491. X#endif  /* BSD */
  2492. X  flushout();
  2493. X  (void) ioctl(fileno(stdin), TCSETA, &raw);
  2494. X
  2495. X} /* enablesignals() */
  2496. X
  2497. X/* Disable signal handling */
  2498. GLOBL VOID disablesignals()
  2499. X{
  2500. X#ifdef BSD
  2501. X  raw.sg_flags &= ~CBREAK;
  2502. X  raw.sg_flags |= RAW;
  2503. X#else   /* SYSV */
  2504. X  raw.c_lflag &= ~ISIG;
  2505. X#endif  /* BSD */
  2506. X  flushout();
  2507. X  (void) ioctl(fileno(stdin), TCSETA, &raw);
  2508. X
  2509. X} /* disablesignals() */
  2510. X
  2511. X/*
  2512. X *      INITIALIZATION AND RESET
  2513. X */
  2514. X
  2515. X/* Init screen, return error message on error */
  2516. GLOBL char *initscreen(term)
  2517. X  register char *term;
  2518. X{
  2519. X  char termcap[TCAPLEN];
  2520. X  char *cp = termbuf, *pc;
  2521. X
  2522. X  /* Get terminal type and init terminal data base */
  2523. X  if(term == NULL)
  2524. X    return("Terminal variable TERM not defined");
  2525. X  switch(tgetent(termcap, term)) {
  2526. X    case -1 :
  2527. X      return("Terminfo library not found");
  2528. X    case 0 :
  2529. X      return("Unknown terminal type");
  2530. X  }
  2531. X
  2532. X  /* Get all needed terminal capabilities from data base */
  2533. X  if((columns = tgetnum("co")) <= 0)
  2534. X    columns = MINCOLS;
  2535. X  if((lines   = tgetnum("li")) <= 0)
  2536. X    lines = MINLINS;
  2537. X  UP = tgetstr("up", &cp);
  2538. X  BC = tgetstr("bc", &cp);
  2539. X  if(pc = tgetstr("pc", &cp))
  2540. X    PC = *pc;
  2541. X  _CM = tgetstr("cm", &cp);
  2542. X  _CL = tgetstr("cl", &cp);
  2543. X  _CE = tgetstr("ce", &cp);
  2544. X
  2545. X  /* Cursor motion, clear screen and clear line must be defined! */
  2546. X  if(_CM == NULL || _CE == NULL || _CL == NULL)
  2547. X    return("Terminal too stupid");
  2548. X
  2549. X  _XR = tgetflag("xr");
  2550. X  _MS = tgetflag("ms");
  2551. X  _SG = tgetnum("sg");
  2552. X#ifdef  BSD
  2553. X  _UG = tgetnum("ug");
  2554. X#else   /* SYSV */
  2555. X  _UG = _SG;
  2556. X#endif  /* BSD */
  2557. X  _CD = tgetstr("cd", &cp);
  2558. X  _TI = tgetstr("ti", &cp);
  2559. X  _TE = tgetstr("te", &cp);
  2560. X  _KS = tgetstr("ks", &cp);
  2561. X  _KE = tgetstr("ke", &cp);
  2562. X  if((_ME = tgetstr("me", &cp)) == NULL)
  2563. X    _ME = tgetstr("se", &cp);
  2564. X  if((_MR = tgetstr("mr", &cp)) == NULL)
  2565. X    _MR = tgetstr("so", &cp);
  2566. X  if(_US = tgetstr("us", &cp)) {
  2567. X    if((_UE = tgetstr("ue", &cp)) && _ME && EQU(_ME, _UE))
  2568. X      _UE = NULL;
  2569. X  }
  2570. X  /* No more video attributes and no cursor visibility functions for   */
  2571. X  /* terminals with standout mode and/or underline glitch (i.e. bando) */
  2572. X  if(_UG <= 0 && _SG <= 0) {
  2573. X    _MB = tgetstr("mb", &cp);
  2574. X    _MD = tgetstr("md", &cp);
  2575. X    _MH = tgetstr("mh", &cp);
  2576. X    _VS = tgetstr("vs", &cp);
  2577. X    _VI = tgetstr("vi", &cp);
  2578. X    _VE = tgetstr("ve", &cp);
  2579. X  }
  2580. X  _IC = tgetstr("ic", &cp);
  2581. X  _DC = tgetstr("dc", &cp);
  2582. X  _AL = tgetstr("al", &cp);
  2583. X  _DL = tgetstr("dl", &cp);
  2584. X  _CS = tgetstr("cs", &cp);
  2585. X  _NL = tgetstr("nl", &cp);
  2586. X  _CR = tgetstr("cr", &cp);
  2587. X  _LE = tgetstr("le", &cp);
  2588. X  _DO = tgetstr("do", &cp);
  2589. X  _SF = tgetstr("sf", &cp);
  2590. X  _SR = tgetstr("sr", &cp);
  2591. X  _SC = tgetstr("sc", &cp);
  2592. X  _RC = tgetstr("rc", &cp);
  2593. X  _BL = tgetstr("bl", &cp);
  2594. X
  2595. X#ifdef  AIX
  2596. X  _AC = tgetstr("bx", &cp);     /* Use box1 (bx) instead of acsc (ac) */
  2597. X  if( !(_AS = tgetstr("as", &cp)))
  2598. X    _AS = tgetstr("f1", &cp);   /* 3.2: Use font1 (f1) instead of smacs (as) */
  2599. X  if( !(_AE = tgetstr("ae", &cp)))
  2600. X    _AE = tgetstr("f0", &cp);   /* 3.2: Use font0 (f0) instead of rmacs (ae) */
  2601. X#else   /* ACSC */
  2602. X  _EA = tgetstr("eA", &cp);
  2603. X  _AC = tgetstr("ac", &cp);
  2604. X  _AS = tgetstr("as", &cp);
  2605. X  _AE = tgetstr("ae", &cp);
  2606. X# ifdef  XENIX  /* RG 11/22/91 */
  2607. X  if(_AC == NULL) {
  2608. X    _AC = "";                   /* Use empty string _AC as flag */
  2609. X    _AS = tgetstr("GS", &cp);
  2610. X    _AE = tgetstr("GE", &cp);
  2611. X    _G2 = tgetstr("G2", &cp);
  2612. X    _GH = tgetstr("GH", &cp);
  2613. X    _G1 = tgetstr("G1", &cp);
  2614. X    _GV = tgetstr("GV", &cp);
  2615. X    _G4 = tgetstr("G4", &cp);
  2616. X    _G3 = tgetstr("G3", &cp);
  2617. X    _GD = tgetstr("GD", &cp);
  2618. X    _GL = tgetstr("GL", &cp);
  2619. X    _GU = tgetstr("GU", &cp);
  2620. X    _GR = tgetstr("GR", &cp);
  2621. X    _GC = tgetstr("GC", &cp);
  2622. X  }
  2623. X# endif /* XENIX */
  2624. X#endif  /* AIX */
  2625. X
  2626. X  if(_CS && !_SF) {
  2627. X    if(_DO)
  2628. X      _SF = _DO;
  2629. X    else if(_NL)
  2630. X      _SF = _NL;
  2631. X    else
  2632. X      _SF = "\n";
  2633. X  }
  2634. X  if(_VS && !_VE)
  2635. X    _VE = _VS;
  2636. X
  2637. X  /* Set capability flags */
  2638. X  glitchcap = _UG > 0 || _SG > 0;
  2639. X  scrollcap = (_AL && _DL) || (_CS && _SF && _SR);
  2640. X  cursorcap = 0;
  2641. X  if(_VE && _VI)
  2642. X    cursorcap |= CF_VISIBLE|CF_INVISIBLE;
  2643. X  if(_SC && _RC)
  2644. X    cursorcap |= CF_SAVE|CF_RESTORE;
  2645. X  videocap = 0;
  2646. X  if(_MR)
  2647. X    videocap |= VA_REVERSE;
  2648. X  if(_MB)
  2649. X    videocap |= VA_BLINK;
  2650. X  if(_MD)
  2651. X    videocap |= VA_BOLD;
  2652. X  if(_MH)
  2653. X    videocap |= VA_HALF;
  2654. X  if(_US)
  2655. X    videocap |= VA_UNDERLINE;
  2656. X
  2657. X  /* Initialize key bindings */
  2658. X  initbindings(term, &cp);
  2659. X
  2660. X  /* Get terminal driver data and initialize raw mode */
  2661. X  if(ioctl(fileno(stdin), TCGETA, &tty) < 0)
  2662. X    return("Error in ioctl");
  2663. X#ifdef  STRUCTCOPY
  2664. X  (void) STRUCTCOPY(tty, raw, sizeof(tty));
  2665. X#else   /* STRUCTASSIGN */
  2666. X  raw = tty;
  2667. X#endif  /* STRUCTCOPY */
  2668. X
  2669. X#ifdef BSD
  2670. X  ospeed = tty.sg_ospeed;
  2671. X  raw.sg_flags |= ANYP|RAW;
  2672. X  raw.sg_flags &= ~(ECHO|XTABS);
  2673. X#else   /* SYSV */
  2674. X  raw.c_cc[VMIN] = 1;
  2675. X  raw.c_cc[VTIME] = 0;
  2676. X  raw.c_iflag |= IGNBRK;
  2677. X  raw.c_iflag &= ~(ICRNL|ISTRIP);
  2678. X  raw.c_oflag |= ONLCR|TAB0;
  2679. X  raw.c_cflag |= CS8;
  2680. X  raw.c_cflag &= ~PARENB;
  2681. X  raw.c_lflag &= ~(ECHO|ICANON|ISIG);
  2682. X#endif  /* BSD */
  2683. X
  2684. X#if     !defined(BSD) && !defined(HASFIONREAD)
  2685. X  /* Get keyboard flag and set to no delay mode */
  2686. X  kbflag = fcntl(fileno(stdin), F_GETFL, 0) & O_NDELAY;
  2687. X#endif  /* !BSD && !HASFIONREAD */
  2688. X
  2689. X  return(NULL);
  2690. X
  2691. X} /* initscreen() */
  2692. X
  2693. X/* Restore screen and exit */
  2694. GLOBL VOID exitscreen(rval)
  2695. X  int rval;
  2696. X{
  2697. X  cursorset(CF_VISIBLE);
  2698. X  (void) cursorxy(0, lines-1);
  2699. X  terminalreset(1);
  2700. X  flushout();
  2701. X  exit(rval);
  2702. X
  2703. X} /* exitscreen() */
  2704. X
  2705. END_OF_FILE
  2706. if test 30770 -ne `wc -c <'src/term.c'`; then
  2707.     echo shar: \"'src/term.c'\" unpacked with wrong size!
  2708. fi
  2709. # end of 'src/term.c'
  2710. fi
  2711. echo shar: End of archive 6 \(of 8\).
  2712. cp /dev/null ark6isdone
  2713. MISSING=""
  2714. for I in 1 2 3 4 5 6 7 8 ; do
  2715.     if test ! -f ark${I}isdone ; then
  2716.     MISSING="${MISSING} ${I}"
  2717.     fi
  2718. done
  2719. if test "${MISSING}" = "" ; then
  2720.     echo You have unpacked all 8 archives.
  2721.     rm -f ark[1-9]isdone
  2722. else
  2723.     echo You still need to unpack the following archives:
  2724.     echo "        " ${MISSING}
  2725. fi
  2726. ##  End of shell archive.
  2727. exit 0
  2728.