home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / maint / part04 < prev    next >
Encoding:
Text File  |  1992-05-13  |  49.5 KB  |  1,739 lines

  1. Newsgroups: comp.sources.unix
  2. From: peirce@gw.wmich.edu (Leonard J. Peirce)
  3. Subject: v26i052: maint - full-screen file and directory maintenance tool, Part04/07
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: peirce@gw.wmich.edu (Leonard J. Peirce)
  8. Posting-Number: Volume 26, Issue 52
  9. Archive-Name: maint/part04
  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 4 (of 7)."
  18. # Contents:  screen.c
  19. # Wrapped by vixie@cognition.pa.dec.com on Thu May 14 23:05:43 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'screen.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'screen.c'\"
  23. else
  24. echo shar: Extracting \"'screen.c'\" \(47411 characters\)
  25. sed "s/^X//" >'screen.c' <<'END_OF_FILE'
  26. X/******************************************************************************
  27. X*******************************************************************************
  28. X
  29. X   Site:    Western Michigan University Academic Computer Center
  30. X
  31. X   System:    Directory/File System Maintenance
  32. X  
  33. X   Program:    maint
  34. X
  35. X   Version=01    Level=00    01/24/92    Leonard J. Peirce
  36. X
  37. X   Purpose:    Screen-handling routines.  Initialization, messages, etc.
  38. X
  39. X   Arguments:    See individual routines
  40. X
  41. X   External variables:    See individual routines
  42. X
  43. X   External functions:
  44. X
  45. X    Defined:    clean_up, clear_mess, erase_tag, highlite, info_mess,
  46. X            initialize, prompt_getstr, put_buf, put_options,
  47. X            put_pagnum, put_slot, put_spec, put_stat,
  48. X            resize_screen, screen_reset, tag_file, write_mess,
  49. X            xmess
  50. X
  51. X    Called:        file_search, get_scr_num, make_slot, set_nodes
  52. X
  53. X   Files accessed:    None
  54. X
  55. X   Return codes:    See individual routines
  56. X
  57. X   Compiling instructions:    See Makefile
  58. X
  59. X   Linking instructions:    See Makefile
  60. X
  61. X   Other information:    Copyright (C) 1992, Leonard J. Peirce
  62. X
  63. X********************************************************************************
  64. X*******************************************************************************/
  65. X
  66. X/******************************************************************************/
  67. X/*                                                                            */
  68. X/*                        # I N C L U D E   F I L E S                         */
  69. X/*                                                                            */
  70. X/******************************************************************************/
  71. X
  72. X#ifdef ultrix
  73. X#include <cursesX.h>
  74. X#else
  75. X#include <curses.h>
  76. X#endif
  77. X#include <sys/param.h>
  78. X#include <stdio.h>            /* who knows?    (NULL maybe?)          */
  79. X#include <ctype.h>
  80. X#include <signal.h>
  81. X#include <string.h>
  82. X#if !defined(SYSV) || defined(sun)
  83. X#include <sys/types.h>
  84. X#endif
  85. X#include <memory.h>
  86. X#include "maint.h"            /* our very own header file          */
  87. X
  88. X/******************************************************************************/
  89. X/*                                                                            */
  90. X/*                             # D E F I N E S                                */
  91. X/*                                                                            */
  92. X/******************************************************************************/
  93. X
  94. X/******************************************************************************/
  95. X/*                                                                            */
  96. X/*          S T R U C T U R E S ,   U N I O N S ,   T Y P E D E F S           */
  97. X/*                                                                            */
  98. X/******************************************************************************/
  99. X
  100. X/******************************************************************************/
  101. X/*                                                                            */
  102. X/*   E X T E R N A L   D E F I N I T I O N S   &   D E C L A R A T I O N S    */
  103. X/*                                                                            */
  104. X/******************************************************************************/
  105. X
  106. extern     WINDOW      *stat_win,
  107. X          *spec_win,
  108. X          *main_win;
  109. X
  110. extern     int      main_rows,
  111. X          make_slot(),
  112. X          strtcpy(),
  113. X          file_search();
  114. X    
  115. extern     short      get_scr_num();
  116. X
  117. extern     void      set_nodes(),
  118. X          cont_after_stop();
  119. X
  120. X     int      put_slot(),
  121. X          put_buf();
  122. X
  123. X     void      initialize(),
  124. X          put_stat(),
  125. X          put_spec(),
  126. X          put_pagnum(),
  127. X          put_options(),
  128. X          prompt_getstr(),
  129. X          screen_reset(),
  130. X          clear_mess(),
  131. X          highlite(),
  132. X          write_mess(),
  133. X          tag_file(),
  134. X          erase_tag(),
  135. X          clean_up(),
  136. X          resize_screen();
  137. X
  138. X/******************************************************************************/
  139. X/*                                                                            */
  140. X/*     S T A T I C   D E F I N I T I O N S   &   D E C L A R A T I O N S      */
  141. X/*                                                                            */
  142. X/******************************************************************************/
  143. X
  144. static   char      user_erase = '\0';
  145. X
  146. static     int      put_line();
  147. X
  148. static     void      adjust_str();
  149. X          
  150. X/*******************************************************************************
  151. X********************************************************************************
  152. X
  153. X  Function:    initialize
  154. X
  155. X  Purpose:    Allocate all of the windows that will be needed and initialize
  156. X        all of the screen parameters needed.
  157. X
  158. X  Global variables:
  159. X
  160. X    Name            Examine/Modify/Use/Read/Write
  161. X    ----            -----------------------------
  162. X    main_rows              X
  163. X    user_erase              X     X
  164. X    LINES                    X
  165. X    COLS
  166. X
  167. X  Return Codes:
  168. X
  169. X    Code            Reason
  170. X    ----            ------
  171. X    none
  172. X
  173. X********************************************************************************
  174. X*******************************************************************************/
  175. X
  176. void initialize(spec_win,main_win,stat_win,node_row_max,node_col_max)
  177. X                    /*******   FORMAL  PARAMETERS   *******/
  178. X     WINDOW      **spec_win,        /* window for directory spec/page #   */
  179. X          **main_win,        /* window where files are displayed   */
  180. X          **stat_win;        /* summary stats window              */
  181. X     u_short  *node_row_max,    /* max. number of rows in nodes array */
  182. X          *node_col_max;    /* max. # of columns in nodes array   */
  183. X
  184. X{    /*** initialize ***/
  185. X
  186. X   initscr();                /* start things off              */
  187. X   signal(SIGHUP,clean_up);        /* catch interrupt and clean up          */
  188. X   signal(SIGINT,clean_up);        /* catch interrupt and clean up          */
  189. X   signal(SIGQUIT,clean_up);        /* catch interrupt and clean up          */
  190. X   signal(SIGILL,clean_up);        /* catch interrupt and clean up          */
  191. X   signal(SIGFPE,clean_up);        /* catch interrupt and clean up          */
  192. X   signal(SIGBUS,clean_up);        /* catch interrupt and clean up          */
  193. X   signal(SIGSEGV,clean_up);        /* catch interrupt and clean up          */
  194. X   signal(SIGSYS,clean_up);        /* catch interrupt and clean up          */
  195. X   signal(SIGPIPE,clean_up);        /* catch interrupt and clean up          */
  196. X   signal(SIGALRM,clean_up);        /* catch interrupt and clean up          */
  197. X   signal(SIGTERM,clean_up);        /* catch interrupt and clean up          */
  198. X/* signal(SIGCONT,resize_screen);    /* resize and repaint screen          */
  199. X   signal(SIGWINCH,resize_screen);    /* resize and repaint screen          */
  200. X
  201. X#ifndef DEBUG
  202. X   nonl();                /* turn off for debugging          */
  203. X#endif
  204. X
  205. X   cbreak();
  206. X   noecho();
  207. X   user_erase = erasechar();
  208. X
  209. X   /* allocate all of the windows that we will need */
  210. X
  211. X   *spec_win = newwin(SPEC_WINDOW_ROWS,COLS,SPEC_WINDOW_START_ROW,0);
  212. X
  213. X   main_rows = LINES - (SPEC_WINDOW_ROWS + STAT_WINDOW_ROWS);
  214. X   *main_win = newwin(main_rows,COLS,SPEC_WINDOW_ROWS,0);
  215. X
  216. X   *stat_win = newwin(STAT_WINDOW_ROWS,COLS,SPEC_WINDOW_ROWS+main_rows,0);
  217. X   
  218. X   if(main_rows > MAX_NODE_ROW)
  219. X      *node_row_max = MAX_NODE_ROW;
  220. X   else
  221. X      *node_row_max = main_rows - 1;
  222. X
  223. X   *node_col_max = MAX_NODE_COL;
  224. X
  225. X   /* set some attributes for the windows */
  226. X
  227. X   wattron(*spec_win,A_REVERSE);
  228. X   wattron(*stat_win,A_REVERSE);
  229. X   keypad(*main_win,TRUE);
  230. X
  231. X   return;
  232. X
  233. X}    /*** initialize ***/
  234. X
  235. X/*******************************************************************************
  236. X********************************************************************************
  237. X
  238. X  Function:    clean_up
  239. X
  240. X  Purpose:    Exit handler routine to clean up before exiting.
  241. X
  242. X  Global variables:
  243. X
  244. X    Name            Examine/Modify/Use/Read/Write
  245. X    ----            -----------------------------
  246. X    stat_win                X
  247. X    spec_win                X
  248. X    main_win                X
  249. X
  250. X  Return Codes:
  251. X
  252. X    Code            Reason
  253. X    ----            ------
  254. X    none
  255. X
  256. X********************************************************************************
  257. X*******************************************************************************/
  258. X
  259. void clean_up()
  260. X
  261. X{    /*** clean_up ***/
  262. X
  263. X   werase(stat_win);            /* exit nicely                  */
  264. X   wrefresh(stat_win);
  265. X   clear_mess(main_win);        /* in case a message needs clearing   */
  266. X   nocbreak();
  267. X   delwin(stat_win);
  268. X   delwin(spec_win);
  269. X   delwin(main_win);
  270. X   endwin();
  271. X   exit();
  272. X
  273. X}    /*** clean_up ***/
  274. X
  275. X/*******************************************************************************
  276. X********************************************************************************
  277. X
  278. X  Function:    resize_screen
  279. X
  280. X  Purpose:    Signal handler called when SIGWINCH is detected.
  281. X
  282. X  Global variables:
  283. X
  284. X    Name            Examine/Modify/Use/Read/Write
  285. X    ----            -----------------------------
  286. X    global_row
  287. X
  288. X  Return Codes:
  289. X
  290. X    Code            Reason
  291. X    ----            ------
  292. X    none
  293. X
  294. X********************************************************************************
  295. X*******************************************************************************/
  296. X
  297. void resize_screen()
  298. X
  299. X{    /*** resize_screen ***/
  300. X
  301. X   return;
  302. X
  303. X}    /*** resize_screen ***/
  304. X
  305. X/*******************************************************************************
  306. X********************************************************************************
  307. X
  308. X  Function:    put_stat
  309. X
  310. X  Purpose:    write the directory statistics line in the third virtual
  311. X        display in reverse video; this line will include the number of
  312. X        files and number of blocks for the directory.
  313. X
  314. X  Global variables:
  315. X
  316. X    Name            Examine/Modify/Use/Read/Write
  317. X    ----            -----------------------------
  318. X    COLS                    X
  319. X
  320. X  Return Codes:
  321. X
  322. X    Code            Reason
  323. X    ----            ------
  324. X    none
  325. X
  326. X********************************************************************************
  327. X*******************************************************************************/
  328. X
  329. void put_stat(window,num_block,num_file)
  330. X                    /*******   FORMAL  PARAMETERS   *******/
  331. X     WINDOW      *window;        /* window to write in              */
  332. X     long      num_block;        /* number of blocks in directory      */
  333. X     short      num_file;        /* number of files in directory          */
  334. X
  335. X{    /*** put_stat ***/
  336. X                    /********   LOCAL  VARIABLES   ********/
  337. X     char      buf[BUFSIZ],        /* formatting buffer #1              */
  338. X          buf2[BUFSIZ];        /*     "        "    "              */
  339. X
  340. X
  341. X   /* get the first string */
  342. X
  343. X#if !defined(SYSV) || defined(sun)
  344. X
  345. X   sprintf(buf2," %d files   %d blocks                Press ? for help",
  346. X           num_file,kbytes(dbtob(num_block)));
  347. X#else
  348. X
  349. X   sprintf(buf2," %d files   %d blocks                Press ? for help",
  350. X           num_file,kbytes(num_block));
  351. X
  352. X#endif
  353. X
  354. X   /* now left-justify it with blanks on the right */
  355. X
  356. X   padcpy(buf,buf2,MAX_SCREEN_COLS);
  357. X   buf[COLS] = '\0';            /* terminate things where we want     */
  358. X
  359. X   /* write it to the virtual display */
  360. X
  361. X   mvwaddstr(window,0,STAT_WINDOW_START_ROW,buf);
  362. X   wrefresh(window);
  363. X
  364. X   return;
  365. X
  366. X}    /*** put_stat ***/
  367. X
  368. X/*******************************************************************************
  369. X********************************************************************************
  370. X
  371. X  Function:    put_spec
  372. X
  373. X  Purpose:    write the directory specification/page number line at the top of
  374. X        screen
  375. X
  376. X  Global variables:
  377. X
  378. X    Name            Examine/Modify/Use/Read/Write
  379. X    ----            -----------------------------
  380. X    home_dir                X
  381. X    home_len                X
  382. X
  383. X  Return Codes:
  384. X
  385. X    Code            Reason
  386. X    ----            ------
  387. X    COLS
  388. X
  389. X********************************************************************************
  390. X*******************************************************************************/
  391. X
  392. void put_spec(window,dir_name,home_dir,home_len,num_screen)
  393. X                    /*******   FORMAL  PARAMETERS   *******/
  394. X     WINDOW      *window;        /* window to write to              */
  395. X     char      *dir_name,        /* current directory specification    */
  396. X          *home_dir;        /* home directory string          */
  397. X     int      home_len;        /* length of home_dir              */
  398. X     short      num_screen;        /* number of screens for directory    */
  399. X
  400. X{    /*** put_spec ***/
  401. X                    /********   LOCAL  VARIABLES   ********/
  402. X     char      *tptr,        /* temporary character pointer          */
  403. X          *tptr2;        /*     "     "      "          */
  404. X     int      page_str_len,        /* length of "Page n of m" string     */
  405. X          dir_len,        /* length of directory name          */
  406. X          count,        /* temporary counter              */
  407. X          temp;            /* temporary value              */
  408. X     char      buf1[MAX_SCREEN_COLS+3], /* formatting buffer              */
  409. X          buf2[MAX_SCREEN_COLS+3]; /* formatting buffer #2          */
  410. X
  411. X
  412. X   sprintf(buf2,"Page  1 of %2d",num_screen);
  413. X   page_str_len = strlen(buf2);
  414. X
  415. X   /* if the current directory is a descendant of the user's home,
  416. X    * strip the home directory part out of it
  417. X    */
  418. X
  419. X   dir_len = strlen(dir_name);
  420. X
  421. X   if(strncmp(dir_name,home_dir,home_len) == 0)
  422. X   {
  423. X      /* the user's home directory is definitely a prefix of the current
  424. X       * directory string; now see if matches exactly
  425. X       */
  426. X
  427. X      if(dir_len != home_len)
  428. X      {
  429. X     dir_name = &dir_name[home_len+1];
  430. X     dir_len -= home_len;
  431. X      }
  432. X   }
  433. X
  434. X   temp = COLS - (page_str_len + 1);
  435. X   tptr = dir_name;
  436. X
  437. X   if(dir_len > temp)
  438. X   {
  439. X      /* directory name is too long to fit on the screen; we have to prune
  440. X       * it back; start from the end and work backwords first until we get it
  441. X       * so that it will fit; then look for a nice place to break it
  442. X       */
  443. X
  444. X      tptr = dir_name + ((u_long) dir_len - 1);
  445. X      count = 2;
  446. X
  447. X      while(tptr != dir_name && count < temp)
  448. X      {
  449. X     --tptr;
  450. X     ++count;
  451. X      }
  452. X
  453. X      /* now look for place to break it */
  454. X
  455. X      tptr2 = strchr(tptr,'/');
  456. X
  457. X      if(tptr2 != NULL)
  458. X     tptr = tptr2 + 1L;        /* good, we found a spot          */
  459. X   }
  460. X
  461. X   memset(buf1,' ',sizeof(buf1));    /* clear out any old garbage          */
  462. X
  463. X   if(tptr == dir_name)            /* did we prune the directory name?   */
  464. X      padcpy(buf1,dir_name,MAX_SCREEN_COLS);
  465. X   else
  466. X   {
  467. X      buf1[0] = '*';
  468. X      padcpy(&buf1[1],tptr,MAX_SCREEN_COLS-1);
  469. X   }
  470. X
  471. X   /* right-justify page number string */
  472. X
  473. X   temp = strlen(buf1);
  474. X   strcpy(&buf1[COLS - page_str_len],buf2);
  475. X   temp = strlen(buf1);
  476. X   mvwaddstr(window,0,SPEC_WINDOW_START_ROW,buf1);
  477. X   wrefresh(window);
  478. X
  479. X   return;
  480. X
  481. X}    /*** put_spec ***/
  482. X
  483. X/*******************************************************************************
  484. X********************************************************************************
  485. X
  486. X  Function:    put_pagnum
  487. X
  488. X  Purpose:    write the "Page nn of nn" to the top right of the screen.
  489. X
  490. X  Global variables:
  491. X
  492. X    Name            Examine/Modify/Use/Read/Write
  493. X    ----            -----------------------------
  494. X    none
  495. X
  496. X  Return Codes:
  497. X
  498. X    Code            Reason
  499. X    ----            ------
  500. X    none
  501. X
  502. X********************************************************************************
  503. X*******************************************************************************/
  504. X
  505. void put_pagnum(window,curr_screen,num_screen)
  506. X                    /*******   FORMAL  PARAMETERS   *******/
  507. X     WINDOW      *window;        /* window to write in              */
  508. X     short      curr_screen,        /* current screen number          */
  509. X          num_screen;        /* number of screens for directory    */
  510. X
  511. X{    /*** put_pagnum ***/
  512. X                    /********   LOCAL  VARIABLES   ********/
  513. X     char      buf[MAX_SCREEN_COLS+1]; /* for formatting things          */
  514. X
  515. X
  516. X   sprintf(buf,"Page %2d of %2d",curr_screen,num_screen);
  517. X   mvwaddstr(window,0,COLS - strlen(buf),buf);
  518. X   wrefresh(window);
  519. X
  520. X   return;
  521. X            
  522. X}    /*** put_pagnum ***/
  523. X
  524. X/*******************************************************************************
  525. X********************************************************************************
  526. X
  527. X  Function:    put_options
  528. X
  529. X  Purpose:    Write the options line to the statistics/options virtual
  530. X        display.  The keystroke needed to invoke the command is written
  531. X        in bold, the rest of the command in normal.
  532. X
  533. X  Global variables:
  534. X
  535. X    Name            Examine/Modify/Use/Read/Write
  536. X    ----            -----------------------------
  537. X    COLS               X
  538. X
  539. X  Return Codes:
  540. X
  541. X    Code            Reason
  542. X    ----            ------
  543. X    none
  544. X
  545. X********************************************************************************
  546. X*******************************************************************************/
  547. X
  548. void put_options(window)
  549. X                    /*******   FORMAL  PARAMETERS   *******/
  550. X     WINDOW      *window;        /* window to write in              */
  551. X
  552. X{    /*** put_options ***/
  553. X                    /********   LOCAL  VARIABLES   ********/
  554. register OPT_DEF  *opt_ptr;        /* pointer to options array          */
  555. register int      column,        /* current column number for writing  */
  556. X          length,        /* current length of options line     */
  557. X          index;        /* index into options[]              */
  558. static     OPT_DEF  options[] =        /* options array for 80-column mode   */
  559. X{
  560. X{"d","el",1,2,1},
  561. X{"r","en",1,2,1},
  562. X{"p","rot",1,3,1},
  563. X{"c","opy",1,3,1},
  564. X{"u","nmark",1,5,1},
  565. X{"e","dit",1,3,1},
  566. X{"+","",1,0,1},
  567. X{"-","",1,0,1},
  568. X{"!","",1,0,1},
  569. X{"/","",1,0,1},
  570. X{".","",1,0,1},
  571. X{"s","elect",1,5,1},
  572. X{"f","in",1,2,1},
  573. X{"x","ecute",1,5,1},
  574. X{"q","uit",1,3,1},
  575. X{"t","ext",1,3,1},
  576. X{"i","nfo",1,3,1},
  577. X#if defined(SYSV) && !defined(sun)
  578. X{"g","roup",1,4,1},
  579. X{"o","wner",1,4,1},
  580. X#endif
  581. X{"b","ranch",1,5,1},
  582. X{"^g","o",2,1,1},
  583. X#if !defined(SYSV) || defined(sun)
  584. X{"g","roup",1,4,1},
  585. X{"o","wner",1,4,1},
  586. X#endif
  587. X{"O","ptions",1,6,1},
  588. X{"","",0,0,0}
  589. X};
  590. X
  591. X
  592. X   wattroff(window,A_REVERSE);        /* make sure the window is set right  */
  593. X
  594. X   /* first see how many options will fit on the screen */
  595. X
  596. X   index = 0;
  597. X   length = 0;
  598. X
  599. X   while(length <= COLS - 1 && options[index].key_len > 0)
  600. X   {
  601. X      length = length + options[index].key_len + options[index].rem_len +
  602. X           options[index].spaces;
  603. X      index++;
  604. X   }
  605. X
  606. X   if(length - options[index].spaces > COLS)
  607. X      index--;                /* don't use last one if no room      */
  608. X
  609. X   opt_ptr = &options[0];
  610. X
  611. X   column = 0;                /* make sure we start ok          */
  612. X   wmove(window,STAT_WINDOW_ROWS - 1,0);
  613. X
  614. X   while(index--)
  615. X   {
  616. X      /* write the key that activates the option in bright mode */
  617. X
  618. X      wattron(window,A_BOLD);
  619. X      waddstr(window,opt_ptr->keystr);
  620. X      wattroff(window,A_BOLD);
  621. X
  622. X      /* write the rest of the command name in normal video */
  623. X
  624. X      waddstr(window,opt_ptr->remaining);
  625. X
  626. X      /* skip the length of the remaining command name AND the number of
  627. X       * spaces that separates this command from the next
  628. X       */
  629. X
  630. X      column += (int) opt_ptr->key_len + (int) opt_ptr->spaces +
  631. X        (int) opt_ptr->rem_len;
  632. X      wmove(window,STAT_WINDOW_ROWS - 1,column);
  633. X      opt_ptr++;            /* go to next option slot          */
  634. X   }
  635. X
  636. X   wattron(window,A_REVERSE);        /* this window is normally REVERSE    */
  637. X   wrefresh(window);
  638. X   return;
  639. X
  640. X}    /*** put_options ***/
  641. X
  642. X/*******************************************************************************
  643. X********************************************************************************
  644. X
  645. X  Function:    screen_reset
  646. X
  647. X  Purpose:    Called when something has changed the format of the screen
  648. X        and we have to make sure that the cursor still points to the
  649. X        right place.  The current file is located and the row, column,
  650. X        and screen values are reset/recalculated.
  651. X
  652. X  Global variables:
  653. X
  654. X    Name            Examine/Modify/Use/Read/Write
  655. X    ----            -----------------------------
  656. X    none
  657. X
  658. X  Return Codes:
  659. X
  660. X    Code            Reason
  661. X    ----            ------
  662. X    none
  663. X
  664. X********************************************************************************
  665. X*******************************************************************************/
  666. X
  667. void screen_reset(nodes,dirptr,filename,node_row,node_col,scr_file,
  668. X             curr_screen,node_row_max,num_file,num_slot,
  669. X             num_screen,slot_width,num_row,num_col)
  670. X                    /*******   FORMAL  PARAMETERS   *******/
  671. X     NODE_DEF nodes[][MAX_NODE_COL+1]; /* screen node matrix          */
  672. X     ENT_DEF  *dirptr;        /* pointer to directory information   */
  673. X     char      *filename;        /* filename to search for          */
  674. X           short      *node_row,        /* current node array row          */
  675. X          *node_col,        /* current node array column          */
  676. X          *scr_file,        /* number of files for current screen */
  677. X          *curr_screen;        /* current screen of directory          */
  678. X     u_short  node_row_max;        /* max. row in nodes array          */
  679. X     short       num_file,          /* number of files in current direct. */
  680. X          num_slot,        /* number of slots per screen          */
  681. X          num_screen,        /* number of screens in directory     */
  682. X          slot_width,        /* width of one screen slot          */
  683. X          num_row,        /* number of rows on the screen          */
  684. X          num_col;        /* number of columns on the screen    */
  685. X
  686. X{    /*** screen_reset ***/
  687. X                    /********   LOCAL  VARIABLES   ********/
  688. X     short      temp,            /* temporary variable and return code */
  689. X          temp2,        /* temporary variable number two      */
  690. X          new_screen;        /* temporary current screen number    */
  691. X
  692. X
  693. X   /* find the file in memory so we can calculate what page it is supposed to
  694. X    * be on
  695. X    */
  696. X
  697. X   temp = (short) file_search(dirptr,filename,num_file,strlen(filename));
  698. X
  699. X   if(temp >= 0)
  700. X   {
  701. X      /* we should ALWAYS get here, because the directory name should not
  702. X       * disappear from our memory, right?
  703. X       */
  704. X
  705. X      new_screen = (temp / num_slot) + 1;
  706. X
  707. X      /* get us to the current screen */
  708. X
  709. X      temp2 = temp - ((new_screen - 1) * num_slot);
  710. X      *node_col = temp2 / num_row;
  711. X      *node_row = temp % num_row;
  712. X                     
  713. X      /* do we need to go to a new screen?  if so, make the new one now */
  714. X
  715. X      if(new_screen != *curr_screen)
  716. X      {
  717. X     /* create the new screen by first putting the new page number in the
  718. X      * upper-right and then rebuilding the main display
  719. X      */
  720. X
  721. X     /* do we need to update the screen node pointers? */
  722. X
  723. X     *curr_screen = new_screen;
  724. X
  725. X     if((new_screen == num_screen) || (*curr_screen == num_screen))
  726. X     {
  727. X        /* set the nodes */
  728. X                                                      
  729. X        set_nodes(nodes,node_row_max,scr_file,num_screen,*curr_screen,
  730. X              num_file,slot_width,num_col);
  731. X     }
  732. X      }
  733. X   }
  734. X
  735. X   return;
  736. X
  737. X}    /*** screen_reset ***/
  738. X
  739. X/*******************************************************************************
  740. X********************************************************************************
  741. X
  742. X  Function:    clear_mess
  743. X
  744. X  Purpose:    Clear an informational message on the screen
  745. X
  746. X  Global variables:
  747. X
  748. X    Name            Examine/Modify/Use/Read/Write
  749. X    ----            -----------------------------
  750. X    main_rows                X
  751. X
  752. X  Return Codes:
  753. X             
  754. X    Code            Reason
  755. X    ----            ------
  756. X    none
  757. X
  758. X********************************************************************************
  759. X*******************************************************************************/
  760. X
  761. void clear_mess(window)
  762. X                    /*******   FORMAL  PARAMETERS   *******/
  763. X     WINDOW      *window;        /* where the message is              */
  764. X
  765. X{    /*** clear_mess ***/
  766. X
  767. X
  768. X   wmove(window,main_rows-1,0);
  769. X   wclrtoeol(window);
  770. X   wrefresh(window);
  771. X   return;
  772. X
  773. X}    /*** clear_mess ***/
  774. X
  775. X/*******************************************************************************
  776. X********************************************************************************
  777. X
  778. X  Function:    highlite
  779. X
  780. X  Purpose:    Rewrite a slot entry for a file, highlighting it if it is
  781. X        necessary.  It will be highlighted if there are commands
  782. X        associated with the file entry.
  783. X
  784. X  Global variables:
  785. X
  786. X    Name            Examine/Modify/Use/Read/Write
  787. X    ----            -----------------------------
  788. X    none
  789. X
  790. X  Return Codes:
  791. X
  792. X    Code            Reason
  793. X    ----            ------
  794. X    none
  795. X
  796. X********************************************************************************
  797. X*******************************************************************************/
  798. X
  799. void highlite(window,buf,ent,args,row,col,slot_width,text_flag)
  800. X                    /*******   FORMAL  PARAMETERS   *******/
  801. X     WINDOW      *window;        /* where to write              */
  802. X     char      *buf;            /* where to put the screen slot          */
  803. X     ENT_DEF  *ent;            /* file entry pointer              */
  804. X     ARG_DEF  *args;        /* run-time arguments              */
  805. X     int      row,            /* column to write it at          */
  806. X          col;            /* row to write it at              */
  807. X     short      slot_width,        /* width of screen slot              */
  808. X          text_flag;        /* whether we display text descrips   */
  809. X
  810. X{    /*** highlite ***/
  811. X                    /********   LOCAL  VARIABLES   ********/
  812. X     int      rend_set;        /* rendition setting for slot entry   */
  813. X
  814. X
  815. X   /* first create the slot */
  816. X
  817. X   if(ent->command != NULL)
  818. X   {
  819. X      rend_set = make_slot(buf,ent,args,slot_width,text_flag);
  820. X
  821. X      /* write the slot */
  822. X
  823. X      put_slot(window,row,col,buf,rend_set);
  824. X   }
  825. X
  826. X   return;
  827. X
  828. X}    /*** highlite ***/
  829. X
  830. X/*******************************************************************************
  831. X********************************************************************************
  832. X
  833. X  Function:    tag_file
  834. X
  835. X  Purpose:    Put a mark by a file on the screen so that user knows what
  836. X        file is being accessed when he is prompted at the bottom of
  837. X        the virtual display for information.  With the cursor at the
  838. X        bottom of the display in preparation for receiving input, it
  839. X        is sometimes hard to remember what file was selected.  This
  840. X        should help alleviate that.
  841. X
  842. X  Global variables:
  843. X
  844. X    Name            Examine/Modify/Use/Read/Write
  845. X    ----            -----------------------------
  846. X    none
  847. X
  848. X  Return Codes:
  849. X
  850. X    Code            Reason
  851. X    ----            ------
  852. X    none
  853. X
  854. X********************************************************************************
  855. X*******************************************************************************/
  856. X
  857. void tag_file(window,row,column)
  858. X                    /*******   FORMAL  PARAMETERS   *******/
  859. X     WINDOW      *window;        /* where to write              */
  860. X     int      row,            /* row of where to write tag          */
  861. X          column;        /* column of where to write tag          */
  862. X
  863. X{    /*** tag_file ***/
  864. X                    /********   LOCAL  VARIABLES   ********/
  865. X
  866. X   /* write the tag character by the file */
  867. X
  868. X   wattron(window,A_BOLD);
  869. X   mvwaddch(window,row,column,TAG_CHAR);
  870. X   wattroff(window,A_BOLD);
  871. X   wrefresh(window);
  872. X   return;
  873. X
  874. X}    /*** tag_file ***/
  875. X
  876. X/*******************************************************************************
  877. X********************************************************************************
  878. X
  879. X  Function:    erase_tag
  880. X
  881. X  Purpose:    Erase a file tag now that user is done doing what they wanted
  882. X        with the file.
  883. X
  884. X  Global variables:
  885. X
  886. X    Name            Examine/Modify/Use/Read/Write
  887. X    ----            -----------------------------
  888. X    none
  889. X
  890. X  Return Codes:
  891. X
  892. X    Code            Reason
  893. X    ----            ------
  894. X    none
  895. X
  896. X********************************************************************************
  897. X*******************************************************************************/
  898. X
  899. void erase_tag(window,row,column)
  900. X                    /*******   FORMAL  PARAMETERS   *******/
  901. X     WINDOW      *window;        /* where to write              */
  902. X     int      row,            /* row of where to write tag          */
  903. X          column;        /* column of where to write tag          */
  904. X
  905. X{    /*** erase_tag ***/
  906. X                    /********   LOCAL  VARIABLES   ********/
  907. X   /* erase the tag */
  908. X
  909. X   mvwaddch(window,row,column,' ');
  910. X   wrefresh(window);
  911. X   return;
  912. X
  913. X}    /*** erase_tag ***/
  914. X
  915. X/*******************************************************************************
  916. X********************************************************************************
  917. X
  918. X  Function:    get_scr_num
  919. X
  920. X  Purpose:    Prompt for and read in a digit string that is supposed to
  921. X        represent the screen number that the user wants to go to.
  922. X        Also check to see if the screen number is valid.
  923. X
  924. X  Global variables:
  925. X
  926. X    Name            Examine/Modify/Use/Read/Write
  927. X    ----            -----------------------------
  928. X    main_rows                X
  929. X
  930. X  Return Codes:
  931. X
  932. X    Code            Reason
  933. X    ----            ------
  934. X    BAD_SCREEN_NO        invalid screen number specified
  935. X    new_screen        new screen number
  936. X    curr_screen        user just hit <RETURN>
  937. X
  938. X********************************************************************************
  939. X*******************************************************************************/
  940. X
  941. short get_scr_num(window,curr_screen,num_screen)
  942. X                    /*******   FORMAL  PARAMETERS   *******/
  943. X     WINDOW      *window;        /* where to read/write              */
  944. X     short      curr_screen,        /* current screen of directory          */
  945. X          num_screen;        /* number of screens in directory     */
  946. X
  947. X{    /*** get_scr_num ***/
  948. X                    /********   LOCAL  VARIABLES   ********/
  949. X     int      new_screen,        /* new screen number              */
  950. X          temp;            /* temporary string length          */
  951. X     char      buf[PAGE_NO_MAX+1];    /* for holding page number string     */
  952. X
  953. X
  954. X   /* prompt for and read it */
  955. X
  956. X   prompt_getstr(window,"Page number? ",buf,main_rows,PAGE_NO_MAX);
  957. X
  958. X   temp = strlen(buf);
  959. X
  960. X   if(temp == 0)
  961. X      return(curr_screen);        /* user didn't specify anything          */
  962. X
  963. X   --temp;                /* move back over the NUL char          */
  964. X
  965. X   /* make sure that this is a string of DIGITS or atoi() will do
  966. X    * weird things
  967. X    */
  968. X
  969. X   while(temp >= 0)
  970. X   {
  971. X      if(isdigit(buf[temp]) || isspace(buf[temp]))
  972. X     temp--;
  973. X      else
  974. X     return(BAD_SCREEN_NO);
  975. X   }
  976. X
  977. X   new_screen = atoi(buf);        /* NOW make it an integer          */
  978. X
  979. X   if((new_screen < 1) || (new_screen > num_screen))
  980. X      return(BAD_SCREEN_NO);        /* bad screen number was specified    */
  981. X
  982. X   return((short) new_screen);        /* return the new screen number          */
  983. X
  984. X}    /*** get_scr_num ***/
  985. X
  986. X/*******************************************************************************
  987. X********************************************************************************
  988. X
  989. X  Function:    put_buf
  990. X
  991. X  Purpose:    Output the current buffer to the display.
  992. X
  993. X        This routine will also wrap long lines.  It will look
  994. X        for the character specified by the separator parameter
  995. X        and wrap it there if it finds one.
  996. X
  997. X        Also, if there is a pad_str specified, it will be inserted
  998. X        at the beginning of the buffer to be printed.
  999. X
  1000. X  Global variables:
  1001. X
  1002. X    Name            Examine/Modify/Use/Read/Write
  1003. X    ----            -----------------------------
  1004. X    COLS
  1005. X
  1006. X  Return Codes:
  1007. X                   
  1008. X    Code            Reason
  1009. X    ----            ------
  1010. X     0            successful
  1011. X    ret_val            return code (possibly successful) from call
  1012. X                to put_buf
  1013. X                                            
  1014. X********************************************************************************
  1015. X*******************************************************************************/
  1016. X
  1017. int put_buf(window,buf,row,max_row,prefix_len,attributes,get_flag,separator,
  1018. X        eof_flag)
  1019. X                    /*******   FORMAL  PARAMETERS   *******/
  1020. X     WINDOW      *window;        /* where to read/write              */
  1021. X     char      *buf;            /* buffer to be written              */
  1022. X     int      *row,            /* row # where line is to be written  */
  1023. X          max_row,        /* max. row in the window          */
  1024. X          prefix_len,        /* length of prefix in line          */
  1025. X          attributes;        /* screen attributes for buffer          */
  1026. X     u_short  get_flag;        /* set if we need to ask for a char   */
  1027. X     char       separator,        /* separator char for wrapping          */
  1028. X          eof_flag;        /* end-of-file from expand()          */
  1029. X
  1030. X{    /*** put_buf ***/
  1031. X                    /********   LOCAL  VARIABLES   ********/
  1032. X     char      *ptr,            /* for splitting long lines          */
  1033. X          *ptr2,        /* ditto.....                  */
  1034. X          *save_ptr;        /* for saving a character pointer     */
  1035. X     char      tchar;        /* for holding one character          */
  1036. static     int       buf_len,        /* length of current buffer          */
  1037. X                 temp_len,        /* temporary length              */
  1038. X          ret_val;        /* return value holder              */
  1039. X
  1040. X
  1041. X   ret_val = 0;                /* set default return value          */
  1042. X   buf_len = strlen(buf);        /* get length of stuff to be written  */
  1043. X
  1044. X   if(eof_flag == TRUE)
  1045. X   {
  1046. X      /* write the EOF record to the inverted co-routine */
  1047. X
  1048. X      ret_val = put_line(window,NULL,row,max_row,attributes,get_flag,TRUE);
  1049. X   }
  1050. X   else
  1051. X   {
  1052. X      if(buf_len >= COLS)        /* too long for screen?              */
  1053. X      {
  1054. X     /* the line is too long so we have to wrap it ourselves by breaking
  1055. X      * the input line up into segments that will fit on the screen
  1056. X      */
  1057. X
  1058. X     ptr = buf;            /* start at the beginning          */
  1059. X     temp_len = buf_len;
  1060. X
  1061. X     while(ptr && temp_len > COLS)
  1062. X     {
  1063. X        /* move backwards until we find a word boundary */
  1064. X
  1065. X        ptr2 = ptr + (u_long) (COLS - 1);
  1066. X        save_ptr = ptr2;        /* so we can go back if we need to    */
  1067. X
  1068. X        while(*ptr2 != separator && ptr2 != ptr + prefix_len)
  1069. X           --ptr2;
  1070. X                
  1071. X        if(ptr2 == ptr + prefix_len) /* couldn't find a word boundary?    */
  1072. X           ptr2 = save_ptr;        /* nope, go back to where we were     */
  1073. X
  1074. X        tchar = *(ptr2 + 1);    /* make the segment a string          */
  1075. X        *(ptr2 + 1) = '\0';
  1076. X
  1077. X        /* output the segment */
  1078. X
  1079. X        ret_val = put_line(window,ptr,row,max_row,attributes,get_flag,
  1080. X                   eof_flag);
  1081. X
  1082. X        *(ptr2 + 1) = tchar;    /* restore the segment              */
  1083. X        prefix_len = 0;        /* only good for first pass thru      */
  1084. X        ptr = ptr2 + 1L;        /* skip this segment              */
  1085. X        temp_len = strlen(ptr);
  1086. X     }
  1087. X
  1088. X     /* if there is a segment left over, write it */
  1089. X
  1090. X     if(temp_len)
  1091. X        ret_val = put_line(window,ptr,row,max_row,attributes,get_flag,
  1092. X                   eof_flag);
  1093. X      }
  1094. X      else
  1095. X      {
  1096. X     /* everything will fit on one line; just write it */
  1097. X
  1098. X     ret_val = put_line(window,buf,row,max_row,attributes,get_flag,
  1099. X                eof_flag);
  1100. X      }
  1101. X   }
  1102. X
  1103. X   return(ret_val);
  1104. X
  1105. X}    /*** put_buf ***/
  1106. X
  1107. X/*******************************************************************************
  1108. X********************************************************************************
  1109. X
  1110. X  Function:    put_line
  1111. X
  1112. X  Purpose:    Inverted co-routine (to put_buf) that controls writing to
  1113. X        the screen and prompting when we reach the bottom.  If get_flag
  1114. X        is TRUE, we force to the bottom of the screen.
  1115. X
  1116. X  Global variables:
  1117. X
  1118. X    Name            Examine/Modify/Use/Read/Write
  1119. X    ----            -----------------------------
  1120. X    LINES                    X
  1121. X
  1122. X  Return Codes:
  1123. X
  1124. X    Code            Reason
  1125. X    ----            ------
  1126. X    SUCCESS
  1127. X    FAILURE
  1128. X                                            
  1129. X********************************************************************************
  1130. X*******************************************************************************/
  1131. X
  1132. static int put_line(window,buf,row,max_row,attr,get_flag,eof_flag)
  1133. X                    /*******   FORMAL  PARAMETERS   *******/
  1134. X     WINDOW      *window;        /* where to read/write              */
  1135. X     char      *buf;            /* buffer to be written              */
  1136. X     int      *row,            /* row where output is to go          */
  1137. X          max_row,        /* max. # of rows for screen          */
  1138. X          attr;            /* attributes to be used          */
  1139. X     u_short  get_flag;        /* set if need to get a char          */
  1140. X     char      eof_flag;        /* used to terminate co-routine          */
  1141. X
  1142. X{    /*** put_line ***/
  1143. X                    /********   LOCAL  VARIABLES   ********/
  1144. static     u_char      state;        /* co-routine state variable          */
  1145. static     char      prompt[] =
  1146. X{"Press any key to continue                                             \
  1147. X                                                                        \
  1148. X                                                 "};
  1149. X
  1150. X
  1151. X   switch(state)            /* perform resuming operation          */
  1152. X   {
  1153. X      case(1):
  1154. X     goto lab0;
  1155. X      default:
  1156. X     prompt[COLS] = '\0';
  1157. X     break;
  1158. X   }
  1159. X
  1160. X   state = 1;                /* so we resume in the right place    */
  1161. X
  1162. X   while(eof_flag == FALSE)
  1163. X   {
  1164. X      while(*row < max_row)
  1165. X      {
  1166. X     /* write the line */
  1167. X
  1168. X     if(buf == NULL || *buf == '\0')
  1169. X     {
  1170. X        mvwaddch(window,*row,0,'x');
  1171. X        mvwdelch(window,*row,0);
  1172. X     }
  1173. X     else
  1174. X     {
  1175. X        if(attr != A_NORMAL)
  1176. X           wattron(window,attr);
  1177. X
  1178. X        mvwaddstr(window,*row,0,buf);    /* write it              */
  1179. X
  1180. X        if(attr != A_NORMAL)
  1181. X           wattroff(window,attr);
  1182. X     }
  1183. X
  1184. X     *row += 1;            /* count this row              */
  1185. X
  1186. X     /* do we need another record? or are we just filling to the bottom
  1187. X      * of the screen?
  1188. X      */
  1189. X
  1190. X     if(get_flag == FALSE)
  1191. X        return(SUCCESS);        /* get another record              */
  1192. X
  1193. lab0:     ;
  1194. X      }
  1195. X
  1196. X      /* we're at the end of a window; prompt and get a char
  1197. X       * we continue
  1198. X       */
  1199. X
  1200. X      wattron(window,A_REVERSE);
  1201. X      mvwaddstr(window,*row,0,prompt);
  1202. X      wattroff(window,A_REVERSE);
  1203. X      wrefresh(window);
  1204. X      wgetch(window);
  1205. X      werase(window);
  1206. X      wrefresh(window);
  1207. X      *row = 0;
  1208. X   }
  1209. X
  1210. X   /* terminate the co-routine */
  1211. X
  1212. X   state = 0;
  1213. X
  1214. X   return(SUCCESS);
  1215. X
  1216. X}    /*** put_line ***/
  1217. X
  1218. X/*******************************************************************************
  1219. X********************************************************************************
  1220. X
  1221. X  Function:    put_slot
  1222. X
  1223. X  Purpose:    Write a file slot to the specified coordinates with the
  1224. X        proper attirbutes.
  1225. X
  1226. X  Global variables:
  1227. X
  1228. X    Name            Examine/Modify/Use/Read/Write
  1229. X    ----            -----------------------------
  1230. X    none
  1231. X
  1232. X  Return Codes:
  1233. X
  1234. X    Code            Reason
  1235. X    ----            ------
  1236. X    mvaddstr()        return code from mvaddstr()
  1237. X                                            
  1238. X********************************************************************************
  1239. X*******************************************************************************/
  1240. X
  1241. int put_slot(window,row,col,string,attr)
  1242. X                    /*******  FORMAL  PARAMETERS   ********/
  1243. X     WINDOW      *window;        /* where to write the slot          */
  1244. X     int      row,            /* screen row                  */
  1245. X          col;            /* screen column              */
  1246. X     char      *string;        /* slot to be written              */
  1247. X     int      attr;            /* attribute to use              */
  1248. X
  1249. X{    /*** put_slot ***/
  1250. X
  1251. X   if(attr != A_NORMAL)            /* turn on the attributes if needed   */
  1252. X      wattron(window,attr);
  1253. X
  1254. X   mvwaddstr(window,row,col,string);
  1255. X
  1256. X   if(attr != A_NORMAL)            /* and turn them back off          */
  1257. X      wattroff(window,attr);
  1258. X
  1259. X   return(SUCCESS);
  1260. X
  1261. X}    /*** put_slot ***/
  1262. X
  1263. X/*******************************************************************************
  1264. X********************************************************************************
  1265. X
  1266. X  Function:    prompt_getstr
  1267. X
  1268. X  Purpose:    Prompt for and get a string from the window.
  1269. X
  1270. X  Global variables:
  1271. X
  1272. X    Name            Examine/Modify/Use/Read/Write
  1273. X    ----            -----------------------------
  1274. X    none
  1275. X
  1276. X  Return Codes:
  1277. X
  1278. X    Code            Reason
  1279. X    ----            ------
  1280. X    mvaddstr()        return code from mvaddstr()
  1281. X                                            
  1282. X********************************************************************************
  1283. X*******************************************************************************/
  1284. X
  1285. void prompt_getstr(window,prompt,buf,row,max_len)
  1286. X                    /*******   FORMAL  PARAMETERS   *******/
  1287. X     WINDOW      *window;        /* where to read/write              */
  1288. X     char      *prompt,        /* prompt user with this          */
  1289. X          *buf;            /* return input string here          */
  1290. X     int      row,            /* row in window to prompt from          */
  1291. X          max_len;        /* max. length string to accept          */
  1292. X
  1293. X{    /*** prompt_getstr ***/
  1294. X                    /********   LOCAL  VARIABLES   ********/
  1295. register short      i;            /* array index                  */
  1296. X     int      prompt_len,        /* length of prompt string          */
  1297. X          column,        /* column where cursor is          */
  1298. X          disp_len;        /* total displayed length of buf      */
  1299. X     short      eoi;            /* end-of-input flag              */
  1300. static     int      ch;            /* keystroke from screen          */
  1301. X
  1302. X
  1303. X   prompt_len = strlen(prompt);
  1304. X   column = prompt_len;
  1305. X   row--;                /* easier than -1 everytime...          */
  1306. X   wattron(window,A_BOLD);
  1307. X   mvwaddstr(window,row,0,prompt);    /* prompt 'em...              */
  1308. X   wattroff(window,A_BOLD);
  1309. X   wrefresh(window);
  1310. X
  1311. X   i = 0;
  1312. X   eoi = FALSE;
  1313. X   disp_len = 0;
  1314. X
  1315. X   while(eoi == FALSE)
  1316. X   {
  1317. X      ch = wgetch(window);
  1318. X
  1319. X      if (ch == user_erase)
  1320. X    ch = KEY_BACKSPACE;
  1321. X
  1322. X      switch(ch)
  1323. X      {
  1324. X     case(CARRIAGE_RETURN):
  1325. X     case(LINEFEED):
  1326. X
  1327. X        eoi = TRUE;            /* break out of the loop          */
  1328. X        buf[i] = '\0';        /* make it a string              */
  1329. X        break;
  1330. X
  1331. X     case(KEY_BACKSPACE):
  1332. X     case(KEY_LEFT):
  1333. X
  1334. X        /* see if we need to shift back to the left */
  1335. X
  1336. X        if(i > 0)            /* anything there to erase?          */
  1337. X        {
  1338. X           --i;
  1339. X           adjust_str(window,buf,&column,row,prompt_len,disp_len,i,LEFT);
  1340. X
  1341. X           if(!iscntrl(buf[i]))
  1342. X          disp_len--;
  1343. X           else
  1344. X          disp_len -= 2;
  1345. X
  1346. X           buf[i] = '\0';        /* erase the character              */
  1347. X        }
  1348. X        else
  1349. X           beep();
  1350. X
  1351. X        break;
  1352. X
  1353. X     case(ESCAPE):
  1354. X
  1355. X        break;
  1356. X
  1357. X     default:
  1358. X
  1359. X        /* the user typed a character */
  1360. X
  1361. X        if(i < max_len)
  1362. X        {
  1363. X           /* add the character to the buffer and see if we need to shift
  1364. X        * to make more room for input
  1365. X        */
  1366. X
  1367. X           if(!iscntrl(ch))
  1368. X          disp_len++;
  1369. X           else
  1370. X          disp_len += 2;
  1371. X
  1372. X           buf[i++] = (char) ch;
  1373. X           adjust_str(window,buf,&column,row,prompt_len,disp_len,i,RIGHT);
  1374. X        }
  1375. X        else
  1376. X           beep();
  1377. X
  1378. X        break;
  1379. X      }
  1380. X   }
  1381. X
  1382. X   buf[i] = '\0';
  1383. X   clear_mess(window);
  1384. X   return;
  1385. X
  1386. X}    /*** prompt_getstr ***/
  1387. X
  1388. X/*******************************************************************************
  1389. X********************************************************************************
  1390. X
  1391. X  Function:    adjust_str
  1392. X
  1393. X  Purpose:    Adjust the string being typed in if it needs it.  If the
  1394. X        user tried to type past the right edge of the screen, shift
  1395. X        things to the left to give him room.  If the user is moving
  1396. X        backwards (via Delete), shift to the right if necessary.
  1397. X
  1398. X  Global variables:
  1399. X
  1400. X    Name            Examine/Modify/Use/Read/Write
  1401. X    ----            -----------------------------
  1402. X    none
  1403. X
  1404. X  Return Codes:
  1405. X
  1406. X    Code            Reason
  1407. X    ----            ------
  1408. X    none
  1409. X                                            
  1410. X********************************************************************************
  1411. X*******************************************************************************/
  1412. X
  1413. static void adjust_str(window,buf,column,row,prompt_len,disp_len,i,direction)
  1414. X                    /*******   FORMAL  PARAMETERS   *******/
  1415. X     WINDOW      *window;        /* where to write              */
  1416. X     char      *buf;            /* where the input is stored          */
  1417. register int      *column;        /* where the cursor is on the screen  */
  1418. X     int      row,            /* row on the screen to write          */
  1419. X          prompt_len,        /* length of prompt string          */
  1420. X          disp_len,        /* total displayed length of buf      */
  1421. X          i;            /* index into buf              */
  1422. X     short      direction;        /* direction on screen we are moving  */
  1423. X
  1424. X{    /*** adjust_str ***/
  1425. X                    /********   LOCAL  VARIABLES   ********/
  1426. static     int      start,        /* loop and array index              */
  1427. X          temp,            /* temporary trash variable          */
  1428. X          count,        /* length of chars to be displayed    */
  1429. X          tcolumn;        /* temporary column value          */
  1430. X
  1431. X
  1432. X   if(direction == RIGHT)
  1433. X   {
  1434. X      /* attempting to move past right edge of the screen? */
  1435. X
  1436. X      if(*column > COLS - 2 || (*column > COLS - 3 && iscntrl(buf[i-1])))
  1437. X      {
  1438. X     /* shift things left to make room; first find where in buf to start
  1439. X      * displaying things
  1440. X      */
  1441. X
  1442. X     start = i - 1;
  1443. X     count = 0;
  1444. X
  1445. X     while(count < MIN_DISP_LEN)
  1446. X     {
  1447. X        if(iscntrl(buf[start]))
  1448. X           count += 2;        /* control chars preceded by ^          */
  1449. X        else
  1450. X           ++count;
  1451. X
  1452. X        --start;
  1453. X     }
  1454. X
  1455. X     /* now write the stuff */
  1456. X
  1457. X     wmove(window,row,prompt_len);
  1458. X     *column = prompt_len;
  1459. X     tcolumn = prompt_len;        /* to cut down on indirect addressing */
  1460. X     wclrtoeol(window);
  1461. X     start++;            /* start in the right place          */
  1462. X
  1463. X     while(start < i)
  1464. X     {
  1465. X        if(iscntrl(buf[start]))
  1466. X        {
  1467. X           /* this is a control character; output the ^ first and
  1468. X        * then convert the character to something printable and
  1469. X        * print it, too
  1470. X        */
  1471. X
  1472. X           mvwaddch(window,row,tcolumn,'^');
  1473. X           waddch(window,buf[start] + 64);
  1474. X           tcolumn += 2;
  1475. X        }
  1476. X        else
  1477. X        {
  1478. X           mvwaddch(window,row,tcolumn,buf[start]);
  1479. X           tcolumn += 1;
  1480. X        }
  1481. X
  1482. X        ++start;
  1483. X     }
  1484. X
  1485. X     *column = tcolumn;        /* now store it                  */
  1486. X      }
  1487. X      else
  1488. X      {
  1489. X     /* we have the room, just write the character */
  1490. X
  1491. X     if(iscntrl(buf[i-1]))
  1492. X     {
  1493. X        mvwaddch(window,row,*column,'^');
  1494. X        waddch(window,buf[i-1] + 64);
  1495. X        *column += 2;
  1496. X     }
  1497. X     else
  1498. X     {
  1499. X        mvwaddch(window,row,*column,buf[i-1]);
  1500. X        *column += 1;
  1501. X     }
  1502. X      }
  1503. X   }
  1504. X   else                    /* moving left                  */
  1505. X   {
  1506. X      /* are we moving past the spot that would cause to shift to
  1507. X       * the right?
  1508. X       */
  1509. X
  1510. X      if(*column == prompt_len + MIN_DISP_LEN ||
  1511. X     (*column == prompt_len + MIN_DISP_LEN + 1 && iscntrl(buf[i])))
  1512. X      {
  1513. X     /* adjust the input line if necessary */
  1514. X
  1515. X     if(disp_len >= COLS - (prompt_len + 1))
  1516. X     {
  1517. X        /* shift the input line to the right so the user can see
  1518. X         * what was typed in
  1519. X         */
  1520. X
  1521. X        start = i - 1;
  1522. X        count = 0;
  1523. X        temp = COLS - (prompt_len + 1);
  1524. X
  1525. X        while(count < temp && start >= 0)
  1526. X        {
  1527. X           if(iscntrl(buf[start]))
  1528. X          count += 2;        /* control chars preceded by ^          */
  1529. X           else
  1530. X          ++count;
  1531. X
  1532. X           --start;
  1533. X        }
  1534. X
  1535. X        /* now write the stuff */
  1536. X
  1537. X        ++start;            /* start in the right spot          */
  1538. X        wmove(window,row,prompt_len);
  1539. X        wclrtoeol(window);
  1540. X        *column = prompt_len;
  1541. X        tcolumn = prompt_len;    /* to cut down on indirect addressing */
  1542. X
  1543. X        while(start < i)
  1544. X        {
  1545. X           if(iscntrl(buf[start]))
  1546. X           {
  1547. X          /* this is a control character; output the ^ first and
  1548. X           * then convert the character to something printable and
  1549. X           * print it, too
  1550. X           */
  1551. X
  1552. X          mvwaddch(window,row,tcolumn,'^');
  1553. X          waddch(window,buf[start] + 64);
  1554. X          tcolumn += 2;
  1555. X           }
  1556. X           else
  1557. X           {
  1558. X          mvwaddch(window,row,tcolumn,buf[start]);
  1559. X          tcolumn += 1;
  1560. X           }
  1561. X
  1562. X           ++start;
  1563. X        }
  1564. X
  1565. X        *column = tcolumn;        /* now store it                  */
  1566. X     }
  1567. X     else
  1568. X     {
  1569. X        /* no need to shift, just move left */
  1570. X
  1571. X        if(iscntrl(buf[i]))
  1572. X        {
  1573. X           *column -= 2;
  1574. X        }
  1575. X        else
  1576. X        {
  1577. X           *column -= 1;
  1578. X        }
  1579. X     }
  1580. X      }
  1581. X      else
  1582. X      {
  1583. X     /* we have room to just move to the left */
  1584. X
  1585. X     if(iscntrl(buf[i]))
  1586. X     {
  1587. X        *column -= 2;
  1588. X     }
  1589. X     else
  1590. X     {
  1591. X        *column -= 1;
  1592. X     }
  1593. X      }
  1594. X
  1595. X      wmove(window,row,*column);
  1596. X      wclrtoeol(window);
  1597. X   }
  1598. X
  1599. X   wrefresh(window);
  1600. X   return;
  1601. X
  1602. X}    /*** adjust_str ***/
  1603. X
  1604. X/*******************************************************************************
  1605. X********************************************************************************
  1606. X
  1607. X  Function:    write_mess
  1608. X
  1609. X  Purpose:    Actually write an informational message to the screen, breaking
  1610. X        up messages that are too long for the screen.
  1611. X
  1612. X  Global variables:
  1613. X
  1614. X    Name            Examine/Modify/Use/Read/Write
  1615. X    ----            -----------------------------
  1616. X    main_win                X
  1617. X    main_rows                X
  1618. X
  1619. X  Return Codes:
  1620. X
  1621. X    Code            Reason
  1622. X    ----            ------
  1623. X    none
  1624. X
  1625. X********************************************************************************
  1626. X*******************************************************************************/
  1627. X
  1628. void write_mess(message,attributes,prefix_len)
  1629. X                    /*******   FORMAL  PARAMETERS   *******/
  1630. X     char      *message;        /* message to be written          */
  1631. X     int      attributes,        /* display attributes              */
  1632. X          prefix_len;        /* length to skip when splitting      */
  1633. X
  1634. X{    /*** write_mess ***/
  1635. X                    /********   LOCAL  VARIABLES   ********/
  1636. X     char      *ptr,            /* for breaking up long messages      */
  1637. X          *ptr2,        /* ditto....                  */
  1638. X          *save_ptr;        /* for saving a pointer              */
  1639. X     int      length;        /* temporary string length          */
  1640. X     char      tchar;        /* for saving a single character      */
  1641. X
  1642. X
  1643. X   /* first clear out things in case the new message is shorter than the
  1644. X    * previous one; we would have garbage at the end of it
  1645. X    */
  1646. X
  1647. X   clear_mess(main_win);        /* clear the message line first          */
  1648. X
  1649. X   if(strlen(message) > COLS)
  1650. X   {
  1651. X      /* message is too long to be written in just one chunk; break it up
  1652. X       * and write them separately
  1653. X       */
  1654. X
  1655. X      ptr = message;            /* start at the beginning          */
  1656. X      prefix_len -= 2;            /* don't count the space          */
  1657. X      length = strlen(ptr);
  1658. X
  1659. X      while(*ptr && length > COLS)
  1660. X      {
  1661. X     wmove(main_win,main_rows-1,0);    /* move cursor back to start of line  */
  1662. X
  1663. X     /* get a full screen-width worth and work backwords to get a break
  1664. X      * point; if we can't find one, take the whole line
  1665. X      */
  1666. X
  1667. X     ptr2 = ptr + (u_long) (COLS - 1);
  1668. X     save_ptr = ptr2;        /* save so we can go back          */
  1669. X
  1670. X     while(!isspace(*ptr2) && ptr2 != ptr + prefix_len)
  1671. X        --ptr2;
  1672. X
  1673. X     if(ptr2 == ptr + prefix_len)    /* did we find a word separator?      */
  1674. X        ptr2 = save_ptr;        /* nope, go back to where we were     */
  1675. X
  1676. X     tchar = *(ptr2 + 1);        /* make the segment a string          */
  1677. X     *(ptr2 + 1) = '\0';
  1678. X     wattron(main_win,attributes);
  1679. X     waddstr(main_win,ptr);        /* write the message segment          */
  1680. X     wattroff(main_win,attributes);
  1681. X     wmove(main_win,main_rows-1,0);    /* move cursor back to start of line  */
  1682. X     wrefresh(main_win);        /* update the screen              */
  1683. X     *(ptr2 + 1) = tchar;        /* restore the character          */
  1684. X     sleep(2);            /* let the user read it              */
  1685. X     prefix_len = 0;        /* only good for first pass          */
  1686. X     ptr = ptr2 + 1L;        /* move to start of next segment      */
  1687. X     length = strlen(ptr);
  1688. X      }
  1689. X
  1690. X      /* if there is a segment left over, write it */
  1691. X
  1692. X      if(length)
  1693. X      {
  1694. X     wmove(main_win,main_rows-1,0);    /* move cursor back to start of line  */
  1695. X     wclrtoeol(main_win);        /* make sure we have a clean line     */
  1696. X     wrefresh(main_win);
  1697. X     wattron(main_win,attributes);
  1698. X     waddstr(main_win,ptr);        /* write the message segment          */
  1699. X     wattroff(main_win,attributes);
  1700. X     wrefresh(main_win);
  1701. X      }
  1702. X   }
  1703. X   else
  1704. X   {
  1705. X      /* write the message, bold */
  1706. X
  1707. X      wattron(main_win,attributes);
  1708. X      mvwaddstr(main_win,main_rows-1,0,message);
  1709. X      wattroff(main_win,attributes);
  1710. X      wrefresh(main_win);
  1711. X   }
  1712. X
  1713. X   return;
  1714. X
  1715. X}    /*** write_mess ***/
  1716. END_OF_FILE
  1717. if test 47411 -ne `wc -c <'screen.c'`; then
  1718.     echo shar: \"'screen.c'\" unpacked with wrong size!
  1719. fi
  1720. # end of 'screen.c'
  1721. fi
  1722. echo shar: End of archive 4 \(of 7\).
  1723. cp /dev/null ark4isdone
  1724. MISSING=""
  1725. for I in 1 2 3 4 5 6 7 ; do
  1726.     if test ! -f ark${I}isdone ; then
  1727.     MISSING="${MISSING} ${I}"
  1728.     fi
  1729. done
  1730. if test "${MISSING}" = "" ; then
  1731.     echo You have unpacked all 7 archives.
  1732.     rm -f ark[1-9]isdone
  1733. else
  1734.     echo You still need to unpack the following archives:
  1735.     echo "        " ${MISSING}
  1736. fi
  1737. ##  End of shell archive.
  1738. exit 0
  1739.