From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  7-JUN-1989 12:32
To:	MRGATE::"ARISIA::EVERHART"
Subj:	MAINT -- Full Screen File/Directory Maintenance (Part 4 of 11)

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Wed,  7 JUN 89 07:01:10 PDT
Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Wed, 7 Jun 89 06:57:04 PDT
Received: by ucbvax.Berkeley.EDU (5.61/1.36)
	id AA18203; Wed, 7 Jun 89 06:42:21 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 7 Jun 89 12:45:31 GMT
From: peirce@gumby.wisc.edu  (Leonard J. Peirce)
Organization: Western Michigan University, Kalamazoo, MI
Subject: MAINT -- Full Screen File/Directory Maintenance (Part 4 of 11)
Message-Id: <739@gumby.cc.wmich.edu>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

+-+-+-+ Beginning of part 4 +-+-+-+
X      full_row = *scr_file / full_col;
X
X   /* first initialize the node matrix just like it would be a full screen;
V    * then we will "trim" the edges to make sure that things point to the rig
Xht
X    * places in case the cursor would to need to wrap around the screen
X    */
X
X   up_val = num_row - 1;
X   i = 0;
X
X   while(i < num_row)
X   `123
X      j = 0;
X      left_val = num_col - 1;`009`009/* left j value`009`009`009      */
X      column_val = 1;
X
X      while(j < num_col)
X      `123
X`009 tptr = &(nodes[i][j]);`009`009/* get a pointer to the current node  */
X`009 tptr->right_col = (j + 1) % num_col;
X`009 tptr->left_col = left_val;
X`009 tptr->up_col = j;
X`009 tptr->down_col = j;
X
X`009 tptr->right_row = i;
X`009 tptr->left_row = i;
X`009 tptr->up_row = up_val;
X`009 tptr->down_row = (i + 1) % num_row;
X
X`009 tptr->row = i + 1;
X`009 tptr->column = column_val;
X`009 column_val = column_val + slot_width + 2;
X`009 left_val = (left_val + 1) % num_col;
X`009 j++;
X      `125
X      up_val = (up_val + 1) % num_row;
X      i++;
X   `125
X
X   /* now trim the edges of the matrix just in case this is the last screen
X    * of the directory
X    */
X
X   /* first go along the top of the screen */
X
X   i = 0;
X   for(j = 0; j < num_col; j++)
X   `123
X      tptr = &(nodes[i][j]);`009`009/* get a pointer to the node`009      */
X      if(!j)`009`009`009`009/* are we in the top left node?`009      */
X      `123
X`009 /* top left node; the values for going up from this node should
X`009  * point to bottom node in the last column on the screen
X`009  */
X
X`009 tptr->up_row = full_row - 1;
X`009 tptr->up_col = num_col - 1;
X      `125
X      else
X      `123
X`009 tptr->up_col = j - 1;
X`009 tptr->up_row = num_row - 1;
X      `125
X   `125
X
X   /* now go along the left of the screen */
X
X   j = 0;
X
X   for(i = 0; i < num_row; i++)
X   `123
X      tptr = &(nodes[i][j]);
X      if(!i)
X      `123
X`009 /* we are in the top left of the screen; going left from here
X`009  * should go to the bottom, right-most node
X`009  */
X
X`009 tptr->left_row = full_row - 1;
X`009 tptr->left_col = num_col - 1;
X      `125
X      else
X      `123
X`009 if(i < full_row + 1)
X`009    tptr->left_col = num_col - 1;
X`009 else
X`009    tptr->left_col = full_col - 1;
X
X`009 tptr->left_row = (i - 1) % num_row;
X      `125
X   `125
X
X   /* trim the bottom full columns */
X
X   i = num_row - 1;
X   for(j = 0; j < full_col; j++)
X   `123
X      tptr = &(nodes[i][j]);`009`009/* get a pointer to the node`009      */
X      tptr->down_col = j + 1;
X   `125
X
X   /* now go along the right side of the last full column */
X
X   j = full_col - 1;
X   for(i = full_row; i < num_row; i++)
X   `123
X      tptr = &(nodes[i][j]);
X      tptr->right_row = (i + 1) % num_row;
X      tptr->right_col = 0;
X   `125
X
X   /* trim along the last column, whether it be full or not */
X
X   j = num_col - 1;
X   for(i = 0; i < full_row; i++)
X   `123
X      tptr = &(nodes[i][j]);
X      tptr->right_row = (i + 1) % num_row;
X      tptr->right_col = 0;
X   `125
X
X   /* set the last node on the screen; this is a special case */
X
X   tptr = &(nodes[full_row-1][num_col-1]);
X   tptr->down_row = 0;
X   tptr->down_col = 0;
X
X   return;
X
X`125`009/*** set_nodes ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009get_args
X
X  Purpose:`009Process the command-line arguments, setting the flags for
X`009`009what arguments are specified and determining the slot width.
X`009`009Also calculate the entry size memory allocation factor for
X`009`009allocating memory pools.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X`009----`009 `009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic void get_args(helplib_d,args,scr_width)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Vstruct`009 dsc$descriptor_s  *helplib_d;`009/* help library descriptor`009
X      */
Xregister ARG_DEF  *args;`009`009/* run-time argument flags`009      */
X`009 short`009  *scr_width;`009`009/* screen width`009`009`009      */
X
X`123`009/*** get_args ***/
X`009     `009`009`009`009/********   LOCAL  VARIABLES   ********/
X`009 ULONG`009  status;`009`009/* return code status holder`009      */
X`009 USHORT`009  leng;`009`009`009/* length returned from CLI$GET_VALUE */
Vstatic`009 char`009  help_buf[STR_MAX+1],`009/* help line for accessing help
X libr. */
X`009`009  buf[STR_MAX+1];`009/* for getting command-line options   */
Vstatic $DESCRIPTOR(help_line,help_buf);`009/* for LBR$OUTPUT_HELP's sake`009
X      */
Vstatic $DESCRIPTOR(conf_d,"CONFIRM");`009/* descriptors for command-line args
X  */
Xstatic $DESCRIPTOR(date_d,"DATE");
Xstatic $DESCRIPTOR(full_d,"FULL");
Xstatic $DESCRIPTOR(help_d,"HELP");
Xstatic $DESCRIPTOR(prot_d,"PROTECTION");
Xstatic $DESCRIPTOR(size_d,"SIZE");
Xstatic $DESCRIPTOR(sort_d,"SORT");
Xstatic $DESCRIPTOR(text_d,"TEXT");
Xstatic $DESCRIPTOR(wide_d,"WIDE");
Xstatic $DESCRIPTOR(file_d,"INFILE");
Vstatic $DESCRIPTOR(buf_d,buf);`009`009/* for getting command-line options   *
X/
X
X            `032
X   if(CLI$PRESENT(&help_d) == CLI$_PRESENT)
X   `123
X
X      /* set up the initialize HELP line, then check to see if anything
X       * was specified on the command line as a sub-topic
X       */
X
X      strcpy(help_buf,"MAINT ");
X
X      if(CLI$GET_VALUE(&file_d,&buf_d,&leng) != CLI$_ABSENT)
X      `123
X`009 /* the user specified a help option on the command line; add it
X`009  * to the help line so that can go right to the topic
X`009  */
X
X`009 buf[leng] = '\0';`009`009/* make it a string first`009      */
X`009 strcat(help_buf,buf);`009`009/* add it to the original help line   */
X      `125
X
X      help_line.dsc$w_length = (USHORT) strlen(help_buf);
X
X      /* allow the user to access the help library and then exit */
X
X      status = LBR$OUTPUT_HELP(LIB$PUT_OUTPUT,0,&help_line,helplib_d,0,
X`009`009`009       LIB$GET_INPUT);
X      if(status != SS$_NORMAL)
X`009 LIB$STOP(status);
X      else
X`009 exit();`009`009`009/* just exit from here`009`009      */
X   `125
X            `032
X   if(CLI$PRESENT(&wide_d) == CLI$_PRESENT)
X   `123
X      args->wide = 1;
X      *scr_width = 132;
X   `125
X   else
X      *scr_width = 80;
X
X   if(CLI$PRESENT(&date_d) == CLI$_PRESENT)
X      args->date = 1;
X
X   if(CLI$PRESENT(&size_d) == CLI$_PRESENT)
X      args->size = 1;
X
X   if(CLI$PRESENT(&prot_d) == CLI$_PRESENT)
X      args->prot = 1;
X
X   if(CLI$PRESENT(&full_d) == CLI$_PRESENT)
X   `123
X      args->full = 1;`009`009`009/* turn on full mode flag`009      */
X      args->prot = 1;
X      args->date = 1;
X      args->size = 1;
X   `125
X
X   if(CLI$PRESENT(&text_d) == CLI$_PRESENT)
X   `123
X      args->text = DISPLAY_TEXT;`009/* we will TRY to display them....    */
X      args->text_startup = TRUE;
X   `125
X
X   if(args->date && args->size && args->prot)
X      args->full = 1;`009`009`009/* might just as well say that the    */
X`009`009`009`009`009/* user specified /FULL`009`009      */
X
X   if(CLI$PRESENT(&sort_d) == CLI$_PRESENT)
X   `123
X      /* find out what the sort option is */
X
X      status = CLI$GET_VALUE(&sort_d,&buf_d,&leng);
X
X      if(status != SS$_NORMAL)
X`009 args->sort = 0;
X      else
X      `123
X`009 /* see what the /SORT option is */
X
X`009 buf[leng] = '\0';`009`009/* make it a string`009`009      */
X`009 if(strcmp(buf,"TYPE") == 0)
X`009    args->sort = TYPE;
X`009 else if(strcmp(buf,"DATE") == 0)
X`009    args->sort = DATE;
X`009 else if(strcmp(buf,"SIZE") == 0)
X`009    args->sort = SIZE;
X`009 else
X`009    args->text = 0;
X      `125
X   `125
X
X   if(CLI$PRESENT(&conf_d) == CLI$_PRESENT)
X      args->confirm = 1;
X
X   return;
X
X`125`009/*** get_args ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:  `009get_dir_mem
X
X  Purpose:`009Compute the amount of memory needed for the current directory
X`009`009and allocate it.  Also set the global pointer to the base of
X`009`009the memory so that it may be used for sorting if so desired.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009baseptr`009`009`009`009  X`009X
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic void get_dir_mem(dirptr,dirsize,num_file)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 ENT_DEF  **dirptr;`009`009/* where to store pointer to memory   */
X`009 long`009  *dirsize;`009`009/* amount of memory allocated`009      */
X`009 short`009  num_file;`009`009/* number of files in directory`009      */
X
X`123`009/*** get_dir_mem ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
X`009 ULONG`009  status;`009`009/* return code status`009`009      */
X
X
X   /* allocate enough memory to hold the information about each of the
X    * files in the current directory; we get the amount of memory by multi-
X    * plying the number of files (plus 1, in case we want to sort them)`032
X    * in the directory by the length the structure definition that holds
X    * the information about a file
X    */
X
X   /* compute how much memory to allocate */
X
X   *dirsize = (long) ((num_file + 1) * sizeof(ENT_DEF));
X
V   status = LIB$GET_VM(dirsize,dirptr); /* attempt to allocate the memory`032
X    */
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);`009`009`009/* bummer.....`009`009`009      */
X
X   baseptr = *dirptr;`009`009`009/* set the global pointer to the      */
X`009`009`009`009`009/* memory allocated for the directory */
X
X   return;
X
X`125`009/*** get_dir_mem ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009get_dir
X
X  Purpose:`009Get the number of files in the current directory, allocate the
X`009`009necessary memory to store the information about the directory,
X`009`009and obtain the information about the individual files.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
X  Termination Codes:
X            `032
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic void get_dir(dirptr,args,num_block,curr_pool,num_file,start_spec,
X`009`009    pool_length,dir_length)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister ENT_DEF  *dirptr;`009`009/* pointer to allocated memory`009      */
Xregister ARG_DEF  *args;`009`009/* run-time argument flags`009      */
X`009 long`009  *num_block;`009`009/* number of blocks in directory      */
X`009 POOL_DEF **curr_pool;`009`009/* pointer to current memory pool     */
X`009 short`009  *num_file;`009`009/* number of files in directory`009      */
X`009 char`009  *start_spec;`009`009/* filespec for getting files`009      */
X`009 long`009  pool_length;`009`009/* length to allocate for new pools   */
X`009 short`009  dir_length;`009`009/* length of current directory string */
X
X`123`009/*** get_dir ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister ULONG`009  status;`009`009/* return code status`009`009      */
X`009 ENT_DEF  *save_ptr;`009`009/* for saving dirptr value`009      */
X`009 short`009  retval = 0;`009`009/* value to return`009`009      */
Vstatic`009 long`009  name_length;`009`009/* length of a filename minus dir-
X    */
X`009`009`009`009`009/* ectory specification`009`009      */
Xregister char`009  *tptr,`009`009/* temporary character pointer`009      */
X`009`009  *name_ptr;`009`009/* pointer to skip directory spec     */
Xstatic`009 ULONG`009  fcontext;`009`009/* FIND_FILE context`009`009      */
Xstatic`009 char`009  buf2[BUFSIZ];`009`009/* resulting string`009`009      */
Vstatic $DESCRIPTOR(file_d,"");`009`009/* descriptor for wildcard string     *
X/
Xstatic $DESCRIPTOR(file2_d,buf2);`009/* resultant file-spec descriptor     */
X
X
X   /* now create the directory entries for each of the files in the
X    * current directory
X    */
X
X   save_ptr = dirptr;`009`009`009/* make a copy of dirptr for later    */
X   fcontext = 0L;`009`009`009/* reset the context`009`009      */
X   name_ptr = &buf2[dir_length];`009/* create a pointer to skip over the  */
X`009`009`009`009`009/* directory name in the file spec    */
X
X   /* use start_spec the first time through here as is; after that, it will
X    * just contain a wildcard spec
X    */
X
X   file_d.dsc$a_pointer = start_spec;
X   file_d.dsc$w_length = (USHORT) strlen(start_spec);  `032
X
X   status = LIB$FIND_FILE(&file_d,&file2_d,&fcontext);
X
X   while(status == RMS$_NORMAL)
X   `123
X      /* make the filename a real string */
X
V      name_ptr = strchr(buf2,']') + 1L;`009/* skip past directory spec`009
X      */
V      tptr = strchr(name_ptr,' ');`009/* find the end of the filename`009`032
X     */
X      *tptr = '\0';`009`009`009/* make the filename a string`009      */
V      name_length = tptr - name_ptr;`009/* calculate length of filename`009
X      */
X            `032
X      /* try to make the directory entry for this file */
X
X      if(make_ent(dirptr,args,curr_pool,name_ptr,num_block,pool_length)
X`009 == RMS$_NORMAL)
X      `123
X`009 /* everything ok so far; store the full filename in a memory pool */
X
X`009 put_pool(&(dirptr->filename),curr_pool,name_ptr,name_length,
X`009`009  pool_length);
X
X`009 dirptr++;`009`009`009/* go to next directory entry`009      */
X      `125
X      else
X`009 *num_file -= 1;`009`009/* bummer; subtract one from num_file */
X
X      status = LIB$FIND_FILE(&file_d,&file2_d,&fcontext);
X   `125
X
X   if(status != RMS$_NMF)`009`009/* did we stop for the right reason?  */
X      LIB$STOP(status);`009`009`009/* nope.....`009`009`009      */
X
X   /* terminate the "finding" of files */
X
X   status = LIB$FIND_FILE_END(&fcontext);
X            `032
X   if((status != SS$_NORMAL) && (status != RMS$_NORMAL))
X      LIB$STOP(status);
X
X   switch(args->sort)`009`009`009/* should we sort......?`009      */
X   `123
X      case(SIZE):`009`009`009/* sort by file size`009`009      */
X
X`009 dirptr->size = ULONG_MAX;
X`009 size_qsort(0,*num_file - 1);
X`009 break;
X
X      case(DATE):`009`009`009/* sort by file access date/time      */
X
X         /* this is commented out because I haven't found a way to compare
X`009  * date quadwords; all that needs to be done is to change time_cmp()
X`009  * so that it can compare them and then uncomment this
X
X`009 dirptr->time[0] = LONG_MAX;
X`009 dirptr->time[1] = ULONG_MAX;
X`009 date_qsort(0,*num_file - 1);
X
X`009  */
X
X`009 break;
X
X      default:
X`009 break;
X   `125
X
V   strcpy(start_spec,"*.*;*");`009`009/* reset start_spec to wildcard`009`032
X     */
X
X   return;
X
X`125`009/*** get_dir ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009put_stat
X
X  Purpose:`009write the directory statistics line in the third virtual
X`009`009display in reverse video; this line will include the number of
X`009`009files and number of blocks for the directory.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
X  Termination Codes:
X                       `032
X`009Code `009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic void put_stat(disp_id,num_block,num_file,scr_width)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 ULONG`009  disp_id;`009`009/* where to write it`009`009      */
X`009 long`009  num_block;`009`009/* numbe of blocks in directory`009      */
X`009 short`009  num_file,`009`009/* number of files in directory`009      */
X`009`009  scr_width;`009`009/* width of screen`009`009      */
X
X`123`009/*** put_stat ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
X`009 ULONG`009  status;`009`009/* return code status`009`009      */
Xstatic`009 char`009  buf[SCR_MAX+1],`009/* formatting buffer`009`009      */
X`009`009  buf2[SCR_MAX];`009/* formatting buffer #2`009`009      */
Xstatic $DESCRIPTOR(text_d,buf);`009`009/* output text descriptor`009      */
X
X
X   /* get the first string */
X
X   sprintf(buf2," %d files   %d blocks",num_file,num_block);
X
X   /* now left-justify it with blanks on the right */
X
X   sprintf(buf,"%-132.132s",buf2);
X   buf[scr_width] = '\0';`009`009/* terminate things where we want     */
X   text_d.dsc$w_length = scr_width;`009/* set width in descriptor`009      */
X
X   /* write it to the virtual display */
X
X   status = SMG$PUT_CHARS(&disp_id,&text_d,&1L,&1L,0,&SMG$M_REVERSE,0,0);
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);
X
X   return;
X
X`125`009/*** put_stat ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009put_spec
X
V  Purpose:`009write the directory specification/page number line at the top o
Xf
X`009`009screen
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009disp1_id`009`009`009`009X
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic void put_spec(disp_id,dir_name,num_screen,scr_width)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 ULONG`009  disp_id;`009`009/* where to write it`009`009      */
X`009 char`009  *dir_name;`009`009/* current directory specification    */
X`009 short`009  num_screen,`009`009/* number of screens for directory    */
X`009`009  scr_width;`009`009/* width of terminal screen`009      */
X
X`123`009/*** put_spec ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
X`009 ULONG`009  status;`009`009/* return code status`009`009      */
X`009 short`009  length;`009`009/* length of stuff in buf2`009      */
Xstatic`009 char`009  buf1[SCR_MAX+1],`009/* formatting buffer`009`009      */
X`009`009  buf2[SCR_MAX+1];`009/* formatting buffer #2`009`009      */
Xstatic $DESCRIPTOR(text_d,buf1);`009/* output descriptor`009`009      */
X
X
V   sprintf(buf1,"%-132.132s",dir_name);`009/* first insert the directory name
X    */
X   sprintf(buf2,"Page  1 of %2d ",num_screen);
V   length = (short) strlen(buf2) + 1;`009/* get length of Page stuff`009 `032
X    */
X   strcat(buf2,"  ");`009`009`009/* add a few spaces to pad things     */
V   strcpy(&buf1[scr_width-length],buf2); /* right-justify it in buf`009  `032
X   */
V   text_d.dsc$w_length = scr_width;`009/* set length of line in descriptor
X   */
X
X   /* now write it to the virtual display */
X
X   status = SMG$PUT_CHARS(&disp_id,&text_d,&1L,&1L,0,&SMG$M_REVERSE,0,0);
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);
X
X   return;
X
X`125`009/*** put_spec ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009put_pagnum
X
X  Purpose:`009write the "Page nn of nn" to the top right of the screen.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009disp1_id`009`009`009`009X
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic void put_pagnum(disp_id,curr_screen,num_screen,scr_width)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 ULONG`009  disp_id;`009`009/* where to write it`009`009      */
X`009 short`009  curr_screen,`009`009/* current screen number`009      */
X`009`009  num_screen,`009`009/* number of screens for directory    */
X`009`009  scr_width;`009`009/* screen width`009`009`009      */
X
X`123`009/*** put_pagnum ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister ULONG`009  status;`009`009/* return code status`009`009      */
X`009 long`009  column;`009`009/* where to start writing stuff`009      */
X`009 short`009  length;`009`009/* length of formatted stuff`009      */
Vstatic`009 char`009  buf[SCR_MAX];`009`009/* for formatting things`009      *
X/
Xstatic $DESCRIPTOR(text_d,buf);`009`009/* output descriptor`009`009      */
X
X
X   sprintf(buf,"Page %2d of %2d ",curr_screen,num_screen);
V   length = (short) strlen(buf) + 1;`009/* get length of Page stuff`009  `032
X   */
X   strcat(buf,"  ");`009`009`009/* add a few spaces to pad things     */
X   column = (long) (scr_width - length) + 1L;
X   text_d.dsc$w_length = length;`009/* set length in descriptor`009      */
X
X   status = SMG$PUT_CHARS(&disp_id,&text_d,&1L,&column,0,&SMG$M_REVERSE,0,0);
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);
X
X   return;
X           `032
X`125`009/*** put_pagnum ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009ctrl_ast
X
X  Purpose:`009Called when an out-of-band character is typed; specifically,
X`009`009this routine is called when a control-C or a control-Y is
X`009`009detected.
X
X  Global variables:
X
X`009Name`009`009     `009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic ULONG ctrl_ast()
X
X`123`009/*** ctrl_ast ***/
X
X   return(SS$_CONTINUE);`009`009/* just go back`009`009`009      */
X  `032
X`125`009/*** ctrl_ast ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009brdcast_ast
X
X  Purpose:`009Called when a broadcast message is detected.  The message is
X`009`009retrieved, examined, and the user is notified by a message in
X`009`009the bottom right-hand corner of the screen.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009paste_id`009`009`009`009X
X`009scr_width`009`009`009`009X
X`009phone_note`009`009`009  X
X`009mail_note`009`009`009  X
X`009disp2_id`009`009`009`009X
X`009disp3_id`009`009`009`009X
X`009global_row`009`009`009`009X
X`009global_col`009`009`009`009X
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009status`009`009`009return code from various system calls
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic void brdcast_ast(ast_arg,arg1,arg2,arg3,arg4)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 ULONG`009  ast_arg,`009`009/* AST argument (none specified)      */
X`009`009  arg1,`009`009`009/* remaining ignored arguments`009      */
X`009`009  arg2,
X`009`009  arg3,
X`009`009  arg4;
X
X`123`009/*** brdcast_ast ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xstatic`009 ULONG`009  status,`009`009/* return code status`009`009      */
X`009`009  column,`009`009/* where to write notification mess.  */
X`009`009  rend_set;`009`009/* rendition setting`009`009      */
Vstatic`009 short`009  length,`009`009/* length of broadcast message`009  `032
X   */
X`009`009  align_val;`009`009/* user for aligning notification     */
Vstatic`009 char`009  mess_buf[MESS_MAX+1],`009/* buffer for getting broadcast
X mess. */
X`009`009  *mailmess = "\7Mail",`009/* mail notification message`009      */
X`009`009  *phonemess = "\7Phone"; /* phone notification message`009      */
Vstatic $DESCRIPTOR(mess_d,mess_buf);`009/* descriptor for retrieving message
X  */
X
X
V   mess_d.dsc$a_pointer = mess_buf;`009/* reset the descriptor just in case
X  */
X   mess_d.dsc$w_length = MESS_MAX;
X
X   /* retrieve the broadcast message */
X
X   status = SMG$GET_BROADCAST_MESSAGE(&paste_id,&mess_d,&length);
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);
X
V   mess_d.dsc$a_pointer[length] = '\0';`009/* terminate the message first`009
X      */
X
X   /* look at the message and determine what kind of message it is */
X
X   if(strindex(mess_buf,"New mail") >= 0)
X   `123
X      /* this is a mail message; send a message to the screen */  `032
X
X      mail_note = 1;`009`009`009/* set a global flag`009`009      */
X      mess_d.dsc$a_pointer = mailmess;
V      align_val = (short) strlen(mailmess); /* get offset of where to put it
X  */
X   `125
X   else if(strindex(mess_buf,"phoning you") >= 0)
X   `123
X      /* someone is phoning */
X
X      phone_note = 1;`009`009`009/* set a global flag`009`009      */
X      mess_d.dsc$a_pointer = phonemess;
X      align_val = (short) (strlen(mailmess) + strlen(phonemess)) + 1;
X   `125
X   else
X      return;`009`009`009`009/* nothing to be concerned about      */
X
X   mess_d.dsc$w_length = (short) strlen(mess_d.dsc$a_pointer);
X   column = (ULONG) (scr_width - align_val) - 1L;
X
X   /* make it blink in reverse video */
X
X   rend_set = SMG$M_REVERSE `124 SMG$M_BLINK;
X
X   status = SMG$PUT_CHARS(&disp3_id,&mess_d,&1L,&column,0,&rend_set,0,0);
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);
X
X   /* reset the cursor to where it was */
X
X   status = SMG$SET_CURSOR_ABS(&disp2_id,global_row,global_col);
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);
X
X   return;
X
X`125`009/*** brdcast_ast ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009make_ent
X
X  Purpose:`009Gather all the information about an individual file, including
X`009`009the protection string and filename that will be displayed on
X`009`009the screen.  This information is stored in the directory entry.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009nullptr`009`009`009`009`009X
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009RMS$_FNF`009`009file was deleted before we could open it
X`009RMS$_NORMAL`009`009file was processed successfully
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic ULONG make_ent(ent,args,pool,filename,num_block,pool_length)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister ENT_DEF  *ent;`009`009`009/* pointer to file entry`009      */
Xregister ARG_DEF  *args;`009`009/* run-time argument flags`009      */
X`009 POOL_DEF **pool;`009`009/* current memory pool`009`009      */
Xregister char`009  *filename;`009`009/* file to be looked up`009`009      */
X`009 long`009  *num_block,`009`009/* number of blocks in directory      */
X`009`009  pool_length;`009`009/* length of pool to allocate`009      */
X
X`123`009/*** make_ent ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister ULONG`009  status;`009`009/* return code status`009`009      */
Xstatic`009 ULONG`009  *tptr;`009`009/* temporary pointer to date/time     */
Vstatic`009 USHORT`009  timelen;`009`009/* length of date/time string`009 `032
X    */
Vstatic`009 short`009  pass;`009`009`009/* whether we have been here before
X   */
Vstatic`009 struct`009  FAB     fab;`009`009/* FAB for getting information`009
X      */
Vstatic`009 struct`009  NAM     nam;`009`009/* NAM  "     "         "`009 `032
X    */
Vstatic`009 struct`009  XABDAT  date_xab;`009/* XAB for getting access date`00
X9      */
Vstatic`009 struct`009  XABPRO  prot_xab;`009/* XAB for getting protection, et
Xc.   */
Vstatic`009 struct`009  XABFHC  head_xab;`009/* XAB for file header`009`009
X      */
Xstatic`009 struct`009  dsc$descriptor_s
X`009`009  time_d =`009`009/* for making date/time string`009      */
X`123DATE_MAX,DSC$K_DTYPE_T,DSC$K_CLASS_S,NULL`125;
X
X
X   if(!pass)`009`009`009`009/* did we already initialize stuff?   */
X   `123
X      fab = cc$rms_fab;`009`009`009/* initialize all of the RMS blocks   */
X      nam = cc$rms_nam;
X      date_xab = cc$rms_xabdat;
X      prot_xab = cc$rms_xabpro;
X      head_xab = cc$rms_xabfhc;
X      fab.fab$l_nam = &nam;
X      fab.fab$l_xab = &date_xab;
X      date_xab.xab$l_nxt = &prot_xab;
X      prot_xab.xab$l_nxt = &head_xab;
V      tptr = &(date_xab.xab$q_rdt);`009/* for accessing date/time quadword
X   */
X      pass = 1;`009`009`009`009/* make sure we do this only once     */
X   `125
X
X   fab.fab$l_fna = filename;`009`009/* set up the filename in the FAB     */
X   fab.fab$b_fns = (UCHAR) strlen(filename);
X  `032
X   status = SYS$OPEN(&fab);`009`009/* open the file to get the info      */
X
X   /* did the file disappear before we could open it?  this could happen
X    * in very volatile directories where files are created and deleted
X    * all the time
X    */
X
X   if(status != RMS$_NORMAL)
X      return(RMS$_FNF);
X  `032
X   /* now extract the information from the RMS blocks */
X
X   /* if the file is not indexed sequential, we want the number of the
X    * end-of-file block for the size; if it IS indexed sequential, we want
X    * the number of the highest virtual block in the file for the size
X    */
X
V   if(fab.fab$b_org != FAB$C_IDX)`009/* relative or sequential file?`009 `032
X    */
X   `123
V      ent->size = head_xab.xab$l_ebk;`009/* yes, use highest block number`032
X     */
X      if(!head_xab.xab$w_ffb)`009`009/* is the highest block being used?   */
X`009 ent->size -= 1;`009`009/* apparently not, so don't count it  */
X   `125
X   else`009`009`009`009`009/* nope, this is indexed sequential   */
X   `123
V      ent->size = head_xab.xab$l_hbk;`009/* use allocation quantity`009  `032
X   */
X   `125
X
X   *num_block += ent->size;`009`009/* add to total blocks for directory  */
X   ent->prot = prot_xab.xab$w_pro;`009/* get the protection word`009      */
X
X   if(args->prot)`009`009`009/* does the user want protection?     */
X   `123
X      ent->prot_str = get_pool_mem(pool,pool_length,PROT_MAX);
X
X      /* create the protection string from the integer value */
X
X      prot_val_to_str(ent->prot,ent->prot_str);
X   `125
X   else`009     `009`009`009`009/* nope, not this time.....`009      */
X   `123
V      ent->prot_str = nullptr;`009`009/* make sure nothing is there`009  `032
X   */
X   `125
X
X   /* save the date quadword just for fun...... */
X
X   ent->time[0] = *tptr;
X   ent->time[1] = *(tptr + 1);
X
X   if(args->date)`009`009`009/* does user want the date string?    */
X   `123
X      /* yes, get the revision date/time string */
X
X      ent->date_str = get_pool_mem(pool,pool_length,DATE_MAX);
X      time_d.dsc$a_pointer = ent->date_str;
X
X      status = SYS$ASCTIM(&timelen,&time_d,tptr,0L);
X
X      if((status != SS$_NORMAL) && (status != SS$_BUFFEROVF))
X`009 LIB$STOP(status);
X
V      ent->date_str[DATE_MAX] = '\0';`009/* terminate the date string`009`032
X     */
X   `125
X   else`009     `009`009`009`009/* nope, not this time.....`009      */
X   `123
X      ent->date_str = nullptr;`009`009/* kill the date string`009`009      */
X   `125
X
X   /* set the filename that will be displayed; if the set_name function
X    * determines that the filename is too long in either the filename or
X    * the extension to be displayed on the screen, the FLAG_CHAR will be
X    * appended to the filename
X    */
X
X   set_name(ent->scr_name,filename);
X
X   ent->command = NULL;`009`009`009/* no commands for file yet`009      */
X   ent->text = nullptr;`009`009`009/* make null for now`009`009      */
X
X   SYS$CLOSE(&fab);`009`009`009/* close the file`009`009      */
X
X   return(RMS$_NORMAL);
X     `032
X`125`009/*** make_ent ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009set_name
X
X  Purpose:`009Extract the necessary parts of the filename to create the
X`009`009filename that will be displayed on the screen.  This means
X`009`009truncation parts of the file specification that are too long
X`009`009to be displayed.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009retval`009`009`0091 = filename too long to be displayed on
X`009`009`009`009screen
X`009`009`009`0090 = filename can be displayed as it
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X   `009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic void set_name(scr_name,filename)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Vregister char`009  *scr_name,`009`009/* name that will be displayed`009  `032
X   */
X`009`009  *filename;`009`009/* filename to pick apart`009      */
X
X`123`009/*** set_name ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister short`009  temp;`009`009`009/* loop and array index`009`009      */
X  `009 short`009  flag = 0;`009`009/* long filename flag`009`009      */
X
X
X   temp = FILENAME_MAX;`009`009`009/* max. number of chars for filename  */
X
X   /* copy the filename part up to the maximum number of characters OR
X    * until a period is encountered
X    */
X
X   while((*filename != '\0') && (*filename != '.') && (temp-- > 0))
X      *scr_name++ = *filename++;
X
X   if(*filename != '.')`009`009`009/* was the filename too long?`009      */
X      flag = 1;`009`009`009`009/* yep...`009`009`009      */
X
X   /* pad with spaces until temp is exhausted */
X
X   while(temp-- > 0)
X      *scr_name++ = ' ';
X
X   /* make sure we are past the period   */
X
X   while((*filename != '\0') && (*filename != '.'))
X      filename++;
X
X   filename++;`009`009`009`009/* skip the period`009`009      */
X   *scr_name++ = '.';`009`009`009/* put in the period ourselves`009      */
X
X   temp = TYPE_MAX;`009`009`009/* maximum number of chars for type   */
X
X   /* copy the filetype part up to the maximum number of characters OR
X    * until a semicolon is encountered
X    */
X
X   while((*filename != '\0') && (*filename != ';') && (temp-- > 0))
X      *scr_name++ = *filename++;
X
X   if(*filename != ';')`009`009`009/* was the filename too long?`009      */
X      flag = 1;`009`009`009`009/* yep...`009`009`009      */
X            `032
X   /* pad with spaces until temp is exhausted */
X
X   while(temp-- > 0)
X      *scr_name++ = ' ';
X
X   /* make sure we are past the semicolon */
X
X   while((*filename != '\0') && (*filename != ';'))
X      filename++;
X
X   filename++;
X   *scr_name++ = ';';`009`009`009/* put in the semicolon ourselves     */
X
X   temp = VERSION_MAX;`009`009`009/* max.  number of chars for version  */
X
X   while((*filename != '\0') && (temp-- > 0))
X      *scr_name++ = *filename++;
X
X   if(*filename)`009`009`009/* was the filename too long?`009      */
X      flag = 1;`009`009`009`009/* yep...`009`009`009      */
X
X   /* pad with spaces until temp is exhausted */
X
X   while(temp-- > 0)
X      *scr_name++ = ' ';
X
X   if(!flag)
X      *scr_name++ = ' ';`009`009/* no flag for this file`009      */
X   else
V      *scr_name++ = FLAG_CHAR;`009`009/* filename was too long; flag it.... *
X/
X
X   *scr_name = '\0';`009`009`009/* terminate the filename`009      */
X
X   return;
X
X`125`009/*** set_name ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009name_qsort
X
X  Purpose:`009Sort the directory entries by filename.
X
X`009`009Algorithm for quicksort from "Fundamentals of Data Structures",
X`009`009Ellis Horowitz and Sartaj Sahni, page 137.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009baseptr`009`009`009`009`009X
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic void name_qsort(m,n)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister short`009  m,`009`009`009/* lower-bound of sub-array to be     */
X`009`009`009`009`009/* sorted`009`009`009      */
X`009`009  n;`009`009`009/* upper-bound of sub-array to be     */
X`009`009`009`009`009/* sorted`009`009`009      */
X
X`123`009/*** name_qsort ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister long`009  i,`009`009`009/* loop and array index`009`009      */
X`009`009  j;`009`009`009/*  "    "    "     "`009`009      */
Xstatic`009 char`009  *temp,`009`009/* used for interchanging pointers    */
X`009`009  *key,`009`009`009/* pointer to key value`009`009      */
X`009`009  tflag;`009`009/* for swapping filename flags`009      */
X
X
X   if(m < n)
X   `123
X      i = m;
X      j = n + 1;
V      key = (baseptr+m)->filename;`009/* get pointer to filename key`009 `032
X    */
X
X      for(;;)
X      `123
X`009 do
X`009 `123
X`009    ++i;
X`009 `125
X`009 while(strcmp((baseptr+i)->filename,key) < 0);
X
X`009 do
X`009 `123
X`009    --j;
X`009 `125
X`009 while(strcmp((baseptr+j)->filename,key) > 0);
X
X`009 if(i < j)
X`009 `123
X`009    /* swap the pointers to the filenames and the flags that indicate
X`009     * whether or not the filename is too long for all of it to be
X`009     * displayed on the screen
X`009     */
X
X`009    temp = (baseptr+i)->filename;
X`009    (baseptr+i)->filename = (baseptr+j)->filename;
X`009    (baseptr+j)->filename = temp;
X`009 `125
X`009 else
X`009    break;
X
X      `125 /* for(;;) */
X
X      temp = (baseptr+m)->filename;
X      (baseptr+m)->filename = (baseptr+j)->filename;
X      (baseptr+j)->filename = temp;
X
X      name_qsort(m,j-1);
X      name_qsort(j+1,n);
X
X   `125 /* if(m < n) */
X
X   return;
X
X`125`009/*** name_qsort ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009make_screen
X
X  Purpose:`009Create the individual screen entries for the current screen
X`009`009of the directory and write them to the virtual display.
X
X`009`009This routine will also clear out the slots on the screen where
X`009`009the files should not appear.  This would happen only on the
X`009`009last page of a directory.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
X  Termination Codes:       `032
X
X`009Code`009`009`009Reason
X`009---- `009`009`009------
X`009none`032
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Vstatic void make_screen(nodes,dirptr,args,disp_id,curr_screen,num_file,scr_fi
Xle,
X`009`009`009num_slot,slot_width,text_flag)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 NODE_DEF nodes[][MAX_NODE_COL+1]; /* screen node matrix`009      */
X`009 ENT_DEF  *dirptr;`009`009/* pointer to directory information   */
Xregister ARG_DEF  *args;`009`009/* command-line arguments`009      */
X`009 ULONG`009  disp_id;`009`009/* display id of where to write`009      */
X`009 short`009  curr_screen,`009`009/* current screen number`009      */
X`009`009  num_file;`009`009/* number of files in directory`009      */
Xregister short`009  scr_file;`009`009/* number of files for current screen */
X`009 short`009  num_slot,`009`009/* number of slots per screen`009      */
X`009`009  slot_width,`009`009/* width of a filename screen slot    */
X`009`009  text_flag;`009`009/* whether we display text descrips   */
X
X`123`009/*** make_screen ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister ENT_DEF  *ent;`009`009`009/* pointer to current directory entry */
Xregister ULONG `009  status;`009`009/* return code status`009`009      */
Vregister short`009  file_count = 0;`009/* number of files processed`009  `032
X   */
Vstatic`009 ULONG`009  rend_set;`009`009/* rendition setting for slots`009`032
X     */
Xstatic`009 long`009  scr_row,`009`009/* what row on screen to write to     */
X`009`009  scr_col,`009`009/* what column on screen to write to  */
X`009`009  len;`009`009`009/* where we are in buf`009`009      */
Xstatic`009 short`009  i,`009`009`009/* loop and array index`009`009      */
X`009`009  j;`009`009`009/*  "    "    "     "`009`009      */
Xstatic`009 char`009  *tptr;`009`009/* temporary string pointer`009      */
Xstatic`009 char`009  buf[SCR_MAX+1],`009/* formatting buffer`009`009      */
X`009`009  buf2[PROT_MAX+1],`009/* formatting buffer #2`009`009      */
X`009`009  blank_slot[] =`009/* for blanking out file slots`009      */
X"                                                                      \
X                                                    ";
Vstatic $DESCRIPTOR(text_d,buf);`009`009/* descriptor for writing to display
X  */
X
X
X
X   /* get pointer to the first directory entry for the current screen */
X
X   ent = dirptr + (ULONG) ((curr_screen - 1) * num_slot);
V   text_d.dsc$a_pointer = buf;`009`009/* reset the descriptor just in case  *
X/
X   text_d.dsc$w_length = slot_width;
X   j = 0;
X
X   while((j < MAX_NODE_COL) && (file_count < scr_file))
X   `123
X      i = 0;
V      scr_col = nodes[i][j].column + 1;`009/* get column value for now`009
X      */
X      scr_row = 1;
X
X      while((i < MAX_NODE_ROW) && (file_count < scr_file))
X      `123
X`009 /* create the screen slot for the file; this included determining
X`009  * if we need to put something special up in case the file has
X`009  * some command(s) associated with it
X`009  */
X
X`009 if(!make_slot(buf,ent,args,slot_width,text_flag))
X`009    rend_set = SMG$M_NORMAL;
X`009 else
X`009    rend_set = SMG$M_BOLD;
X
X`009 text_d.dsc$w_length = (USHORT) strlen(buf);
X
X`009 /* now write the file information to the screen in the right spot */
X
X`009 status = SMG$PUT_CHARS(&disp_id,&text_d,&scr_row,&scr_col,0,
X`009`009`009`009&rend_set,0,0);
X
X`009 if(status != SS$_NORMAL)
X`009    LIB$STOP(status);
X
X`009 i++;`009`009`009`009/* move to next column`009`009      */
X`009 file_count++;`009`009`009/* count this file as processed`009      */
X`009 scr_row++;`009`009`009/* move to next row on screen`009      */
X`009 ent++;`009`009`009`009/* go to next directory entry`009      */
X      `125
X
X      j++;`009`009`009`009/* go down the screen node matrix     */
X   `125
X
X   if(num_slot > scr_file)`009`009/* do we need to clear out some of    */
X   `123`009`009`009`009`009/* the slots on the screen?`009      */
X      /* clear out the slots */
X
X      j--;`009`009`009`009/* take off the last increment so     */
X`009`009`009`009`009/* we start in the right column`009      */
V      blank_slot[slot_width] = '\0';`009/* terminate the blank slot line `032
X    */
X      text_d.dsc$w_length = (USHORT) slot_width;
X      text_d.dsc$a_pointer = blank_slot;
X
X      while((j < MAX_NODE_COL) && (file_count < num_slot))
X      `123
X`009 while((i < MAX_NODE_ROW) && (file_count < num_slot))
X`009 `123
X`009    /* now blank out the file slot in the virtual display */
X
X`009    status = SMG$PUT_CHARS(&disp_id,&text_d,&scr_row,&scr_col,0,0,0,0);
X
X`009    if(status != SS$_NORMAL)
X`009       LIB$STOP(status);
X
X`009    i++;`009`009`009/* move to next column`009`009      */
X`009    file_count++;`009`009/* count this file as processed`009      */
X`009    scr_row++;`009`009`009/* move to next row on screen`009      */
X`009 `125
X
X`009 i = 0;`009`009`009`009/* start the rows over`009`009      */
X`009 j++;`009`009`009`009/* move right one column`009      */
X`009 scr_row = 1L;
X`009 scr_col = scr_col + slot_width + 2;
X      `125
X   `125
X
X   return;
X
X`125`009/*** make_screen ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009file_select
X
X  Purpose:`009Process a file that has been selected.  This includes pasting/
X`009`009unpasting the virtual display for the file and processing the
X`009`009options associated with the file.  The file is presented to the
X`009`009user in a series of screens.  After each screen is displayed,
X`009`009the user has the option of continuing to view the file or
X`009`009quit and return to the directory.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009  0`009`009`009File selection completed successfully
X`009CANT_OPEN`009`009Error opening file
X`009CANT_DISPLAY`009`009Error displaying file on screen
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic short file_select(filename,buf,disp_id,paste_id,keybd_id,scr_width)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 char`009  *filename,`009`009/* name of file to be accessed`009      */
X`009`009  *buf;`009`009`009/* reading buffer`009`009      */
X`009 ULONG`009  disp_id,`009`009/* display to write to`009`009      */
X`009`009  paste_id,`009`009/* pasteboard id`009`009      */
-+-+-+-+-+ End of part 4 +-+-+-+-+-

