home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / utree / part06 < prev    next >
Encoding:
Text File  |  1992-09-06  |  75.0 KB  |  2,722 lines

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