home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / maint / part04 / screen.c
Encoding:
C/C++ Source or Header  |  1992-05-13  |  46.3 KB  |  1,691 lines

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