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

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Thu,  8 JUN 89 07:31:02 PDT
Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Thu, 8 Jun 89 07:31:38 PDT
Received: by ucbvax.Berkeley.EDU (5.61/1.36)
	id AA03030; Thu, 8 Jun 89 07:12:46 -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: 8 Jun 89 13:23:14 GMT
From: peirce@gumby.wisc.edu  (Leonard J. Peirce)
Organization: Western Michigan University, Kalamazoo, MI
Subject: MAINT -- Full Screen File/Directory Maintenance (Part 8 of 11)
Message-Id: <743@gumby.cc.wmich.edu>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

+-+-+-+ Beginning of part 8 +-+-+-+
X      tptr = ent->command;`009`009/* else use the one already there     */
X   `125
X
X   ptr = buf;`009`009`009`009/* convert filename to all uppercase  */
X   while(*ptr)
X   `123
X      *ptr = _toupper(*ptr);
X      ptr++;
X   `125
X
X   /* is there already enough room to put the new name in a memory pool? if
X    * there is, just reuse the memory we already have; otherwise, free up
X    * the memory (if there is any) and allocate some to hold the new name
X    */
X
X   if(command == COPY)
X   `123
X      if(length > tptr->copy_len)
X      `123
X`009 /* nope, we need more memory; first free the old memory if there
X`009  * was any
X`009  */
X
X`009 if(tptr->copy_len != 0)
X`009 `123
X`009    str_size = (long) tptr->copy_len;
X
X`009    status = LIB$FREE_VM(&str_size,&(tptr->copy_name));
X
X`009    if(status != SS$_NORMAL)
X`009       LIB$STOP(status);
X`009 `125
X
X`009 /* now allocate some new memory to hold the longer filename */
X
X`009 str_size = (long) length;
X`009 status = LIB$GET_VM(&str_size,&(tptr->copy_name));
X
X`009 if(status != SS$_NORMAL)
X`009    LIB$STOP(status);
X
X`009 tptr->copy_len = length;`009/* save the length of the memory      */
X      `125
X
X      dest_ptr = tptr->copy_name;`009/* get where to copy the filename to  */
X      tptr->comm_copy = 1;`009`009/* set the command in the structure   */
X   `125
X   else
X   `123
X      if(length > tptr->ren_len)
X      `123
X`009 /* nope, we need more memory; first free the old memory if there
X`009  * was any
X`009  */
X
X`009 if(tptr->ren_len != 0)
X`009 `123
X`009    str_size = (long) tptr->ren_len;
X
X`009    status = LIB$FREE_VM(&str_size,&(tptr->ren_name));
X
X`009    if(status != SS$_NORMAL)
X`009       LIB$STOP(status);
X`009 `125
X
X`009 /* now allocate some new memory to hold the longer filename */
X
X`009 str_size = (long) length;
X`009 status = LIB$GET_VM(&str_size,&(tptr->ren_name));
X
X`009 if(status != SS$_NORMAL)
X`009    LIB$STOP(status);
X
X`009 tptr->ren_len = length;`009/* save the length of the memory      */
X      `125
X
X      dest_ptr = tptr->ren_name;`009/* get where to copy the filename to  */
X      tptr->comm_ren = 1;`009`009/* set the command in the structure   */
X      tptr->comm_del = 0;`009`009/* rename implies no delete`009      */
X   `125
X
X   strcpy(dest_ptr,buf);`009`009/* copy it to the right place`009      */
X
X   return(0);
X
X`125`009/*** mark_copy_ren ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:  `009mark_text
X
X  Purpose:  `009The selected file is to get a text descriptor; allocate the
X`009`009memory for the command structure (if necessary), link it to
X`009`009the file entry,`009and set the command in the command structure.
X
X  Global variables:
X                         `032
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`009completed successfully
X`009 -1`009`009`009problems allocating memory
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009status`009`009`009status of various failed LIB$ calls
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X  `032
Xshort mark_text(ent,pool,disp_id,keybd_id,pool_length,scr_width)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Vregister ENT_DEF  *ent;`009`009`009/* entry for file to be deleted`009      *
X/
X`009 POOL_DEF **pool;`009`009/* pointer to current pool structure  */
X`009 long`009  disp_id,`009`009/* display id for virtual display     */
X`009`009  keybd_id,`009`009/* keyboard id`009`009`009      */
X`009    `009  pool_length;`009`009/* length of pool if we need another  */
X`009 short`009  scr_width;`009`009/* width of screen`009`009      */
X
X`123`009/*** mark_text ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister COM_DEF  *tptr;`009`009/* temporary command structure ptr    */
X `009 ULONG`009  status;`009`009/* return code status holder`009      */
X`009 long`009  str_size,`009`009/* amount of memory to allocate`009      */
X`009`009  column;`009`009/* column of where to write`009      */
X`009 USHORT`009  length;`009`009/* length of string read in`009      */
Vstatic`009 char`009  buf[TEXT_MAX+1],`009/* array for text descriptor`009`032
X     */
X`009`009  prompt[] =`009`009/* for prompting the user`009      */
X`009`009  `123"Text descriptor: "`125;
Vstatic $DESCRIPTOR(buf_d,buf);`009`009/* descriptor for getting filename    *
X/
Xstatic $DESCRIPTOR(limit_d,"<");
Xstatic $DESCRIPTOR(prompt_d,prompt);
X
X
X   buf[0] = '\0';`009`009`009/* reset the buffer`009`009      */
X
X   /* first put the character that marks the maximum number of characters
X    * that can be specified for the text descriptor
X    */
X
X   column = (long) (TEXT_MAX +  strlen(prompt)) + 1L;
X   status = SMG$PUT_CHARS(&disp_id,&limit_d,&MAIN_ROWS,&column,0,&SMG$M_BOLD,
X`009`009`009  0,0);
X
X   if(status != SS$_NORMAL)
X      return(-1);
X
X   /* position the cursor to prompt for the text descriptor */
X
X   status = SMG$SET_CURSOR_ABS(&disp_id,&MAIN_ROWS,&1L);
X
X   if(status != SS$_NORMAL)
X      return(-1);  `032
X
X   /* read in the text descriptor */
X
V   status = SMG$READ_STRING(&keybd_id,&buf_d,&prompt_d,&TEXT_MAX,0,0,0,&lengt
Xh,
X`009`009`009    0,&disp_id,0,&SMG$M_BOLD,0);
X                                    `032
X   /* erase the prompt and the user's response from the virtual display */
X
X   clear_mess(disp_id,scr_width);
X
X   if(status != SS$_NORMAL)
X      return(-1);
X
X   buf[length] = '\0';`009`009`009/* make the filename a string`009      */
X   length++;`009`009`009`009/* don't forget to count the NUL      */
X
X   /* ok, we have the text descriptor; determine if we need to allocate a
X    * command structure for this file or if one already exists from a
X    * previous command
X    */
X
X   if(ent->command == NULL)
X   `123
V      /* we need command structure; allocate it and link it to the file entry
X */
X
X      tptr = new_comm();
X      if(tptr == NULL)
X`009 return(-1);`009`009`009/* problems allocating memory`009      */
X
X      ent->command = tptr;`009`009/* link it to the file entry`009      */
X   `125
X   else
X   `123
X      tptr = ent->command;`009`009/* else use the one already there     */
X   `125
X
X   /* is there already enough room to store the text descriptor?
X    * if there is, just reuse the memory we already have; otherwise,
X    * allocate some new memory
X    */
X
X   if(length > tptr->text_len)
X   `123
V      /* we need more memory; first free up any old memory if there was any *
X/
X
X      if(tptr->text_len != 0)
X      `123
X`009 str_size = (long) tptr->text_len;
X
X`009 status = LIB$FREE_VM(&str_size,&(tptr->text));
X
X`009 if(status != SS$_NORMAL)
X`009    LIB$STOP(status);
X      `125
X
X      /* allocate some memory to hold the text descriptor */
X
X      str_size = (long) length;
X      status = LIB$GET_VM(&str_size,&(tptr->text));
X
X      if(status != SS$_NORMAL)
X`009 LIB$STOP(status);
X
X      tptr->text_len = length;`009`009/* we have a new length`009`009      */
X   `125
X
X   strcpy(tptr->text,buf);`009`009/* copy it to its resting place`009      */
X
X   /* set the command in the command structure */
X
X   tptr->comm_text = 1;
X   tptr->comm_del = 0;`009`009`009/* text descriptor implies no delete  */
X
X   return(0);
X
X`125`009/*** mark_text ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:  `009mark_protect
X
X  Purpose:  `009The selected file is to be reprotected; allocate the memory
X`009`009for the command structure (if necessary), link it to the file
X`009`009entry,`009and set the command in the command structure.
X
X  Global variables:
X                         `032
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`009completed successfully
X`009 -1`009`009`009problems allocating memory
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xshort mark_protect(ent,disp_id,keybd_id,scr_width)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Vregister ENT_DEF  *ent;`009`009`009/* entry for file to be deleted`009      *
X/
X`009 long`009  disp_id,`009`009/* display id for virtual display     */
X`009`009  keybd_id;`009`009/* keyboard id`009`009`009      */
X`009 short`009  scr_width;`009`009/* width of screen`009`009      */
X
X`123`009/*** mark_protect ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister COM_DEF  *tptr;`009`009/* temporary command structure ptr    */
Vregister char`009  *ptr;`009`009`009/* temporary character pointer`009      *
X/
X`009 ULONG`009  status;`009`009/* return code status holder`009      */
X`009 long`009  str_size,`009`009/* amount of memory to allocate`009      */
X`009`009  end_col;`009`009/* for erasing the prompt`009      */
X`009 USHORT`009  prot_val;`009`009/* temporary protection value`009      */
V`009 char`009  buf[PROT_INP_MAX+1];`009/* array for protection string`009`032
X     */
X
X
X   buf[0] = '\0';`009`009`009/* initialize input buffer`009      */
X
X   /* prompt for and read in the protection string */
X
X   status = get_string(keybd_id,disp_id,PROT_INP_MAX,buf,"Protection: ",
X`009`009       scr_width);
X
X   if(status != SS$_NORMAL)
X      return(-1);
X
X   /* if nothing was specified for the protection string, just return from
X    * right here
X    */
X
X   if(*buf == '\0')
X      return(0);
X
X   /* now determine if the protection string specified is valid */
X
X   if(prot_str_to_val(buf,&prot_val,ent->prot) == -1)
X      return(-1);`009`009`009/* invalid protection string`009      */
X
X   /* at this point, the protection string has been edited and is considered
X    * valid; get the integer value for the protection string and store it in
X    * in the command structure; first, do we need a command structure or does
X    * the file have one from a previous command?
X    */
X
X   if(ent->command == NULL)
X   `123
V      /* we need command structure; allocate it and link it to the file entry
X */
X
X      tptr = new_comm();
X      if(tptr == NULL)
X`009 return(-1);`009`009`009/* problems allocating memory`009      */
X
X      ent->command = tptr;`009`009/* link it to the file entry`009      */
X   `125
X   else
X   `123
X      tptr = ent->command;`009`009/* else use the one already there     */
X   `125
X
X   tptr->comm_prot = 1;`009`009`009/* set the command in the structure   */
X   tptr->prot = prot_val;`009`009/* set the protection integer value   */
X   tptr->comm_del = 0;`009`009`009/* protection implies no delete`009      */
X
X   return(0);`009`009`009`009/* fine.........`009`009      */
X
X`125`009/*** mark_protect ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:  `009mark_cancel
X
V  Purpose:  `009Cancel all commands for the specified file entry and dealloca
Xte
X`009`009the command structure for the file.
X
X  Global variables:
X                         `032
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`009completed successfully
X`009 -1`009`009`009problems allocating memory
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xvoid mark_cancel(ent)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 ENT_DEF *ent;`009`009`009/* file entry pointer`009`009      */
X
X`123`009/*** mark_cancel ***/
X
X
X   if(ent->command != NULL)
X   `123
X      /* first free up any memory that might be  holding character strings */
X
X      free_comstr(ent->command);
X
X      ent->command = NULL;`009 `009/* no more structure for file entry   */
X   `125
X
X   return;
X
X`125`009/*** mark_cancel ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009init_pool
X
X  Purpose:`009Allocate the first memory pool for the current directory,
X`009`009initializing the pool structure node and initialize all of
X`009`009the other structures to point to null pools.  The remaining
X`009`009pool node structures are linked together in a linked list.
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                `032
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`009LIB$GET_VM() failed
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xvoid init_pool(pool,pool_length)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 POOL_DEF **pool;`009`009/* array of pool node structures      */
X`009 long`009  pool_length;`009`009/* length of pool to allocate`009      */
X
X`123`009/*** init_pool ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister POOL_DEF *tptr;`009`009/* temporary pool node structure ptr  */
Xregister ULONG`009  status;`009`009/* return code status`009`009      */
Vstatic`009 long`009  num_byte;`009`009/* number of bytes to allocate`009 `032
X    */
X
X
X   /* allocate memory for the pool node structure first */
X
X   num_byte = sizeof(POOL_DEF);
X   status = LIB$GET_VM(&num_byte,&tptr);
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);
X
X   /* allocate memory for the first pool and initialize all of the other
X    * accounting stuff associated with it
X    */
X
X   num_byte = pool_length;`009`009/* set up size of pool to allocate    */
X   status = LIB$GET_VM(&num_byte,&(tptr->first));
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);
X
X   /* set up the other stuff for the first memory pool */
X
X   tptr->ptr = tptr->first;`009`009/* set pointer to available memory    */
V   tptr->remaining = num_byte;`009`009/* all bytes in pool available`009 `032
X    */
X   tptr->next_pool = NULL;`009`009/* terminate the linked list....      */
V   tptr->length = pool_length;`009`009/* save original length of pool`009`032
X     */
X   *pool = tptr;`009`009`009/* start everything....`009`009      */
X
X   return;
X
X`125`009/*** init_pool ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009reset_pool
X
X  Purpose:`009reset the pool pointers so that the memory allocated for them
X`009`009can be used again without reallocating the memory for them.
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
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xvoid reset_pool(pool)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister POOL_DEF *pool;`009`009/* memory pool node structures`009      */
X
X`123`009/*** reset_pool ***/                `032
X
X   while(pool != NULL)
X   `123
V      pool->ptr = pool->first;`009`009/* reset available byte pointer`009`032
X     */
V      pool->remaining = pool->length;`009/* reset number of bytes available
X    */
X      pool = pool->next_pool;`009`009/* go to next pool node structure     */
X   `125
X
X   return;
X
X`125`009/*** reset_pool ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009new_pool
X
X  Purpose:`009allocate memory for a pool node structure and the actual
X`009`009memory for the pool; also link the pool to the pool list.
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`009status`009`009`009LIB$GET_VM() failed
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
XPOOL_DEF *new_pool(pool,pool_length)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister POOL_DEF *pool;`009`009/* pointer to current memory pool     */
X`009 long`009  pool_length;`009`009/* length of pool to allocate`009      */
X
X`123`009/*** new_pool ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister POOL_DEF *tptr;`009`009/* temporary pool pointer`009      */
Xregister ULONG`009  status;`009`009/* return code status`009`009      */
X`009 ULONG`009  num_byte;`009`009/* number of bytes to allocate`009      */
X
X
X   /* first see if there is a pool already out there; if there is,
X    * just return so that we don't have to reuse the memory
X    */
X
V   if(pool->next_pool != NULL)`009`009/* is there a pool out there?`009  `032
X   */
V      return(pool->next_pool);`009`009/* yes, just return a pointer to it   *
X/
X
V   /* at this point we have conceded that a new memory pool is needed; alloca
Xte
X    * the structure to hold the new pool's accounting information
X    */
X
V   num_byte = sizeof(POOL_DEF);`009`009/* allocate enough for a structure`032
X   */
X
X   status = LIB$GET_VM(&num_byte,&tptr);
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);
X
X   pool->next_pool = tptr;`009`009/* link to current pool`009`009      */
X   pool = pool->next_pool;`009`009/* move to new pool structure`009      */
X
X   /* now allocate the actual memory for the pool */
X
X   num_byte = pool_length;`009`009/* set length of pool to allocate     */
X
X   status = LIB$GET_VM(&num_byte,&tptr);
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);
X
X   pool->next_pool = NULL;`009`009/* terminate pool list`009`009      */
X   pool->ptr = tptr;`009`009`009/* set available memory pointer`009      */
X   pool->first = tptr;`009`009`009/* save beginning of pool`009      */
X   pool->remaining = pool_length;`009/* set number of bytes available      */
V   pool->length = pool_length;`009`009/* save original pool length`009      *
X/
X
X   return(pool);`009`009`009/* return pointer to new pool struct. */
X
X`125`009/*** new_pool ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009put_pool
X
X  Purpose:`009Copy a string to a memory pool.  If the current pool does not
X`009`009have enough memory to accomodate the string, allocate a new
X`009`009pool first and then copy the string to the new pool.
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
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xvoid put_pool(dest,pool,str,length,pool_length)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 char`009  **dest;`009`009/* where to store pointer to str      */
X`009 POOL_DEF **pool;`009`009/* current memory pool structure      */
X`009 char`009  *str;`009`009`009/* string to be stored in memory pool */
Xregister long`009  length;`009`009/* length of string to be stored      */
X`009 long`009  pool_length;`009`009/* length of pool if we need another  */
X               `032
X`123`009/*** put_pool ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister POOL_DEF *tptr;`009`009/* temporary pool structure pointer   */
X
X
V   if((*pool)->remaining < (length + 1)) /* has the pool run dry....?`009`032
X     */
X   `123
V      *pool = new_pool(*pool,pool_length); /* yes, get another pool`009  `032
X   */
X   `125
X
X   tptr = *pool;`009`009`009/* set up temporary pool struct. ptr. */
X   strcpy(tptr->ptr,str);`009`009/* copy the string to the pool`009      */
X   *dest = tptr->ptr;`009`009`009/* set the pointer to the string      */
V   tptr->ptr = tptr->ptr + length + 1;`009/* update available memory pointer
X    */
X   tptr->remaining = tptr->remaining - (length + 1);
X
X   return;
X
X`125`009/*** put_pool ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009get_pool_mem
X
V  Purpose:`009Return a pointer to a memory slot that will satisfy the request
X.
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`009retptr`009`009`009pointer to memory slot
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xchar *get_pool_mem(pool,pool_length,length)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister POOL_DEF  **pool;`009`009/* current memory pool`009`009      */
X`009 long`009  pool_length,`009`009/* length of pool to request`009      */
X`009`009  length;`009`009/* length of memory slot needed`009      */
X
X`123`009/*** get_pool_mem ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister char`009  *retptr;`009`009/* pointer to return`009`009      */
Xregister POOL_DEF *tptr;`009`009/* used to speed things up a bit....  */
Xstatic`009 short`009  count;
X
X   /* is there enough room in the current memory pool?  If not, allocate
X    * another one and get the memory from there
X    */
X
X   count++;
X   if((*pool)->remaining < (length + 1))
X      *pool = new_pool(*pool,pool_length);
X
X   tptr = *pool;`009`009`009/* make a pointer`009`009      */
X
X   /* we have the memory, whether it is in a new pool or the one we had on
X    * entry; update the pool structure to reflect the memory that we need
X    * to take from it
X    */
X
X   retptr = tptr->ptr;`009`009`009/* save pointer to memory slot`009      */
X   tptr->ptr = tptr->ptr + length + 1L;
X   tptr->remaining = tptr->remaining - (length + 1);
X  `032
X   return(retptr);`009`009`009/* return pointer to slot`009      */
X
X`125`009/*** get_pool_mem ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009free_pool
X
X  Purpose:`009Free the memory of all of the memory pools for a directory,
X`009`009including the node structures for all of the nodes.  This
X`009`009routine will be called when exiting 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:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009status`009`009`009LIB$FREE_VM() failed
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xvoid free_pool(pool)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister POOL_DEF *pool;`009`009/* first pool in pool node list`009      */
X
X`123`009/*** free_pool ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister POOL_DEF *tpool;`009`009/* temporary pool node pointer`009      */
Xregister ULONG`009  status;`009`009/* return code status holder`009      */
X`009 char`009  *tptr;`009`009/* temporary character pointer`009      */
X`009 long`009  tlength;`009`009/* temporary length value`009      */
X
X
X
X   while(pool != NULL)
X   `123
X      /* free the memory for the pool first */
X
X      tptr = pool->first;`009`009/* get pointer to first byte in pool  */
V      tlength = pool->length;`009`009/* get original length of pool`009  `032
X   */
X
X      status = LIB$FREE_VM(&tlength,&tptr);
X      if(status != SS$_NORMAL)
X`009 LIB$STOP(status);
X
V      tpool = pool->next_pool;`009`009/* save pointer to next pool node     *
X/
X
X      /* now free up the memory for the pool node structure */
X
X      tptr = pool;`009`009`009/* get pointer to pool node structure */
V      tlength = (long) sizeof(POOL_DEF);/* get length of node structures `032
X    */
X
X      status = LIB$FREE_VM(&tlength,&tptr);
X      if(status != SS$_NORMAL)
X`009 LIB$STOP(status);
X
X      pool = tpool;`009`009`009/* move to next pool in list`009      */
X   `125
X
X   return;
X
X`125`009/*** free_pool ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009clear_mess
X
X  Purpose:`009Clear an informational message on the screen
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            `032
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xvoid clear_mess(disp_id,scr_width)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 long`009  disp_id;`009`009/* display of where to clear message  */
X`009 short`009  scr_width;`009`009/* width of screen display`009      */
X
X`123`009/*** clear_mess ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
X    `009 ULONG`009  status;`009`009/* return code status holder`009      */
Vstatic`009 long`009  start_row = MAIN_ROWS, /* what row to start in `009 `032
X    */
X`009`009  start_col = 1L,`009/* what column to start in`009      */
X`009`009  end_row = MAIN_ROWS,`009/* what row to end in`009`009      */
X`009`009  end_col;`009`009/* what column to end in`009      */
X
X
X   end_col = (long) scr_width;
X
X   /* clear out the message */
X
X   status = SMG$ERASE_DISPLAY(&disp_id,&start_row,&start_col,&end_row,
X`009`009`009      &end_col);
X
X   return;
X
X`125`009/*** clear_mess ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009prot_val_to_str
X
X  Purpose:`009Create the string representing the file protection for a
X`009`009specific file from the integer value for the protection.
X`009`009This function perhaps could be made general-purpose and put
X`009`009in the WMUCRTL library at a later date.
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`009number of character in protection string
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xshort prot_val_to_str(prot,str)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister USHORT`009  prot;`009`009`009/* protection word value`009      */
Xregister char`009  *str;`009`009`009/* return protection string value     */
X
X`123`009/*** prot_val_to_str ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister char`009  *save;`009`009/* original str value`009`009      */
Xstatic`009 short`009  retval;`009`009/* value to return`009`009      */
X
X
X   save = str;`009`009`009`009/* save where we started from`009      */
X
X   if(!(prot & SYSTEM_READ))
X      *str++ = 'R';
X   if(!(prot & SYSTEM_WRITE))
X      *str++ = 'W';
X   if(!(prot & SYSTEM_EXECUTE))
X      *str++ = 'E';
X   if(!(prot & SYSTEM_DELETE))
X      *str++ = 'D';
X
X   *str++ = ',';`009`009`009/* insert the comma`009`009      */
X
X   if(!(prot & OWNER_READ))
X      *str++ = 'R';
X   if(!(prot & OWNER_WRITE))
X      *str++ = 'W';
X   if(!(prot & OWNER_EXECUTE))
X      *str++ = 'E';
X   if(!(prot & OWNER_DELETE))
X      *str++ = 'D';
X
X   *str++ = ',';`009`009`009/* insert the comma`009`009      */
X
X   if(!(prot & GROUP_READ))
X      *str++ = 'R';
X   if(!(prot & GROUP_WRITE))
X      *str++ = 'W';
X   if(!(prot & GROUP_EXECUTE))
X      *str++ = 'E';
X   if(!(prot & GROUP_DELETE))
X      *str++ = 'D';
X
X   *str++ = ',';`009`009`009/* insert the comma`009`009      */
X
X   if(!(prot & WORLD_READ))
X      *str++ = 'R';
X   if(!(prot & WORLD_WRITE))
X      *str++ = 'W';
X   if(!(prot & WORLD_EXECUTE))
X      *str++ = 'E';
X   if(!(prot & WORLD_DELETE))
X      *str++ = 'D';
X
X   /* calculate how many characters we put in */
X
X   retval = str - save;`009`009`009/* calculate length of string`009      */
X   save += PROT_MAX;`009`009`009/* get where we should end up`009      */
X
X   /* pad the rest of the string with spaces */
X
X   while(str < save)
X      *str++ = ' ';
X
X   *str = '\0';`009`009`009`009/* terminate things`009`009      */
X
X   return(retval);
X
X`125`009/*** prot_val_to_str ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:  `009get_string
X
X  Purpose:  `009Prompt for and read in a string from the display.
X
X  Global variables:
X                         `032
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`009status`009`009`009return code from SMG$READ_STRING
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009status`009`009`009return code from SMG$SET_CURSOR_ABS
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
XULONG get_string(keybd_id,disp_id,max_length,response,prompt,scr_width)
X`009     `009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 long`009  keybd_id,`009`009/* keyboard id`009`009`009      */
X`009`009  disp_id,`009`009/* display id for prompting`009      */
X`009`009  max_length;`009`009/* max. length of response`009      */
X`009 char`009  *response,`009`009/* where to put response`009      */
X`009`009  *prompt;`009`009/* prompt to use`009`009      */
X`009 short`009  scr_width;`009`009/* width of screen display`009      */
X
X`123`009/*** get_string ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
X`009 ULONG`009  status;`009`009/* return code status holder`009      */
X`009 USHORT`009  length;`009`009/* length of string read in`009      */
Xstatic $DESCRIPTOR(prompt_d,"");`009/* descriptor for prompt`009      */
Xstatic $DESCRIPTOR(response_d,"");`009/* descriptor for response`009      */
X
X
V   prompt_d.dsc$a_pointer = prompt;`009/* set up prompt descriptor`009      *
X/
X   prompt_d.dsc$w_length = (USHORT) strlen(prompt);
X   response_d.dsc$a_pointer = response;
X   response_d.dsc$w_length = (USHORT) max_length;
X
X   status = SMG$SET_CURSOR_ABS(&disp_id,&MAIN_ROWS,&1L);
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);
X
X   /* prompt for and read in the response */
X            `032
V   status = SMG$READ_STRING(&keybd_id,&response_d,&prompt_d,&max_length,0,0,0
X,
X`009`009`009    &length,0,&disp_id,0,&SMG$M_BOLD,0);
X
X   if(status != SS$_NORMAL)
X      return(status);
X
X   clear_mess(disp_id,scr_width);`009/* clear out the message`009      */
V   *(response + length) = '\0';`009`009/* make the response a string`009 `032
X    */
X
X   return(status);
X
X`125`009/*** get_string ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009prot_str_to_val
X
X  Purpose:`009Given a VMS protection string and the original integer value
X`009`009for a file's protection, edit the string and if it is valid,
X`009`009calculate the new protection integer value.
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`009Everything fine
X`009 -1`009`009`009Invalid protection string
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic short prot_str_to_val(str,new_val,prot_val)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister char`009  *str;`009`009`009/* protection string`009`009      */
X`009 short`009  *new_val,`009`009/* calculated protection value`009      */
X`009 `009  prot_val;`009`009/* original protection value`009      */
X
X`123`009/*** prot_str_to_val ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xstatic`009 char`009  *tptr,`009`009/* temporary character pointer....    */
X`009`009  *tptr2;`009`009/* ...used for editing protection str */
Xstatic`009 int`009  temp;`009`009`009/* temporary value`009`009      */
Vstatic`009 USHORT`009  mask;`009`009`009/* mask value for constructing value
X  */
Vstatic`009 UCHAR`009  sys_flag,`009`009/* flag for SYSTEM field processed`032
X   */
X`009`009  own_flag,`009`009/*  "    "  OWNER    "       "`009      */
X`009`009  grp_flag,`009`009/*  "    "  GROUP    "`009     "`009      */
X`009`009  wld_flag,`009`009/*  "    "  WORLD    "       "`009      */
X`009`009  r_flag,`009`009/* flag for READ subfield processed   */
X`009`009  w_flag,`009`009/*   "   "  WRITE   "`009      "`009      */
X`009`009  e_flag,`009`009/*   "   "  EXECUTE "`009      "`009      */
X`009`009  d_flag,`009`009/*   "   "  DELETE  "`009      "`009      */
X`009`009  open_flag,`009`009/* flag set for dangling commas`009      */
X`009`009  paren_flag,`009`009/* for checking balanced parentheses  */
X`009`009  ch;`009`009`009/* temporary character holder`009      */
X
X
X   /* first make sure the string is all upper case with no spaces in it */
X
X   tptr = str;`009`009`009`009/* make a copy to use`009`009      */
X   tptr2 = str;`009`009`009`009/* need second copy to squeeze it     */
X
X   while(*tptr)
X   `123
V      if((*tptr != ' ') && (*tptr != 11)) /* skip over spaces and tabs`009
X      */
X      `123
X`009 *tptr2 = _toupper(*tptr);
X`009 tptr2++;
X      `125
X      tptr++;
X   `125
X
X   *tptr2 = '\0';`009`009`009/* make sure it is still a string     */
X
X   if(*str == '(')`009`009`009/* string enclosed in parens?`009      */
X   `123
X      str++;`009`009`009`009/* skip it`009`009`009      */
X      paren_flag = 1;`009`009`009/* yes, remember for later......      */
X   `125
X   else
X      paren_flag = 0;`009`009`009/* nope, clear it`009`009      */
X
X   sys_flag = own_flag = grp_flag = wld_flag = 0;
X
X   while(*str && *str != ')')
X   `123
X      /* get the delineating character for the field designator, whether
X       * it be a comma or a colon
X       */
X
X      open_flag = 0;`009`009`009/* no dangling comma yet`009      */
X      temp = banystr(str,",:");
X
X      /* now terminate it temporarily at the delineator so we can see
X       * what field was specified
X       */
X
X      if(temp >= 0)
X      `123
X`009 ch = *(str+temp);`009`009/* save the character for a while     */
X`009 *(str+temp) = '\0';`009`009/* terminate it there`009`009      */
X      `125
X      else
X      `123
X`009 /* we must lie here and pretend we have a colon to fool the upcoming
X`009  * test
X`009  */
X
X`009 ch = ':';
X`009 temp = 0;`009`009`009/* also lie about the offset`009      */
X      `125
X
X      /* see what subfield we are dealing with */
X
X      if(strindex("SYSTEM",str) == 0)
X      `123
X`009 if(!sys_flag)
X`009 `123
X`009    sys_flag++;`009`009`009/* only do SYSTEM once`009`009      */
X`009    prot_val = prot_val `124 0xF;
X`009    mask = 0x1;
X`009 `125
X`009 else
X`009    return(-1);`009`009`009/* error; field specified twice`009      */
X      `125
X      else if(strindex("OWNER",str) == 0)
X      `123
X`009 if(!own_flag)
X`009 `123
X`009    own_flag++;`009`009`009/* only do OWNER once`009`009      */
X`009    prot_val = prot_val `124 0xF0;
X`009    mask = 0x10;
X`009 `125
X`009 else
X`009    return(-1);
X      `125
X      else if(strindex("GROUP",str) == 0)
X      `123
X`009 if(!grp_flag)
X`009 `123
X`009    grp_flag++;`009`009`009/* only do GROUP once`009`009      */
X`009    prot_val = prot_val `124 0xF00;
X`009    mask = 0x100;
X`009 `125
X`009 else
X`009    return(-1);
X      `125
X      else if(strindex("WORLD",str) == 0)
X      `123
X`009 if(!wld_flag)
X`009 `123
X`009    wld_flag++;`009`009`009/* only do WORLD once`009`009      */
X`009    prot_val = prot_val `124 0xF000;
X`009    mask = 0x1000;
X`009 `125
X`009 else
X`009    return(-1);
X      `125
X      else
X      `123
X`009 /* invalid field specifier means error....... */
X
X`009 return(-1);
X      `125
X
X      /* move the pointer to one character past the delineator character
X       * if it is a colon; if it is a comma, put it on the comma so that
X       * the loop will stop anything from being processed
X       */
X
X      str = str + (ULONG) temp;
X
X      if(ch == ':')
X`009 str++;`009`009`009`009/* skip the colon if there is one     */
X      else
X`009 *str = ch;`009`009`009/* else restore the comma`009      */
X
X      r_flag = w_flag = e_flag = d_flag = 0;
X
X      /* process all parts of the field */
X
X      while(*str && *str != ',' && *str != ')')
X      `123
X`009 switch(*str)
X`009 `123
X`009    case('R'):
X
X`009       if(r_flag)
X`009`009  return(-1);`009`009/* error, two READs for field`009      */
X
X`009       prot_val = prot_val `094 mask;
X`009       r_flag++;`009`009/* only process READ once`009      */
X`009       break;
X
X`009    case('W'):
X
X`009       if(w_flag)
X`009`009  return(-1);`009`009/* error, two WRITEs for field`009      */
X
X`009       prot_val = prot_val `094 (mask << 1);
X`009       w_flag++;`009`009/* only process WRITE once`009      */
X`009       break;
X
X`009    case('E'):
X
X`009       if(e_flag)
X`009`009  return(-1);`009`009/* error, two EXECUTEs for field      */
X
X`009       prot_val = prot_val `094 (mask << 2);
X`009       e_flag++;`009`009/* only process EXECUTE once`009      */
X`009       break;
X
X`009    case('D'):
X
X`009       if(d_flag)
X`009`009  return(-1);`009`009/* error, two DELETEs for field`009      */
X
X`009       prot_val = prot_val `094 (mask << 3);
X`009       d_flag++;`009`009/* only process DELETE once`009      */
X`009       break;
X
X`009    default:`009`009`009/* should never get here`009      */
X`009       return(-1);`009`009/* but it is an error if we do....    */
X`009 `125
X`009 str++;`009`009`009`009/* go to next character in string     */
X      `125
X
X      if(*str == ',')`009`009`009/* if we hit a comma, skip over it    */
X      `123
X`009 str++;
X`009 open_flag++;`009`009`009/* last char was a comma`009      */
X      `125
X   `125
X
X   if(paren_flag && *str != ')')
X      return(-1);`009`009`009/* no right parenthesis`009`009      */
X
X   if(!paren_flag && *str == ')')
X      return(-1);`009`009`009/* no left parenthesis`009`009      */
X
X   if(open_flag)`009`009`009/* was there a dangling comma?`009      */
X      return(-1);`009`009`009/* yup, error........`009`009      */
X
X   *new_val = prot_val;`009`009`009/* send it back`009`009`009      */
X   return(0);
X
X`125`009/*** prot_str_to_val ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009make_slot
X
X  Purpose:`009Make a slot to be displayed on the screen for a file depending
X`009`009on the (possible) commands associated with the file.  In
X`009`009some cases, some funny stuff will be done with the screen
X`009`009slot to connotate that the file has some commands associated
X`009`009with it.
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`009normal slot
X`009  1`009`009`009file has commands; highlite it
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xshort make_slot(buf,ent,args,slot_width,text_flag)
X`009`009`009 `009`009/*******   FORMAL  PARAMETERS   *******/
X`009 char`009  *buf;`009`009`009/* where to put the screen slot`009      */
Xregister ENT_DEF  *ent;`009`009`009/* file entry pointer`009`009      */
Xregister ARG_DEF  *args;`009`009/* run-time arguments`009`009      */
X`009 short`009  slot_width,`009`009/* width of a screen slot`009      */
X`009`009  text_flag;`009`009/* whether we display text descrips   */
X
X`123`009/*** make_slot ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
X`009 short`009  spot = TEXT_MAX;`009/* where to terminate the blank text  */
Xstatic`009 COM_DEF  *ptr;`009`009`009/* pointer to possible command struct */
Vstatic`009 char`009  *prot_ptr,`009`009/* pointer to the protection string
X   */
X`009`009  *text_ptr;`009`009/* pointer to text descriptor`009      */
Vstatic`009 char`009  prot_buf[PROT_MAX+1],`009/* for making protection string
Xs      */
X`009`009  text_buf[TEXT_MAX*2+1], /* for making text descriptors      */
X`009`009  blnk_text[] = `009/* blank text descriptor`009      */
X"                                        ";
X
X
X   /* now see if there are commands associated with the file; we do things
X    * a little differently if there are
X    */
X
X   if(ent->command == NULL)`009`009/* are there commands for this file?  */
X   `123
X      /* no commands associated with this file; just use the information
X       * that came with it to create the slot; first see if we need to
X       * include text descriptors with the slot
X       */
X
V      if(text_flag == DISPLAY_TEXT)`009/* do we display the text descrips?
X   */
X      `123
X`009 /* yes, they don't overflow the file slots; now see if there is one
X`009  * for the current file
X`009  */
X
X`009 if(ent->text != NULL)`009`009/* is there a text descriptor?`009      */
X`009 `123
X`009    /* there IS a text descriptor for this file; pad the text descriptor
X`009     * on the right with spaces so that if there was a descriptor on the
X`009     * screen in this slot (perhaps from a previous page) it will be
X`009     * completely overwritten by the current one
X`009     */
X
X`009    cat(text_buf,ent->text,blnk_text);
V`009    text_buf[TEXT_MAX] = '\0';`009/* only use as much as we need`009 `032
X    */
X`009    text_ptr = text_buf;`009/* set the pointer to the text desc.  */
X`009 `125
X`009 else
X`009    text_ptr = blnk_text;`009/* use a blank text descriptor`009      */
X      `125
X      else
X`009 text_ptr = nullptr;`009`009/* no text descriptor displayed`009      */
X
X      /* no commands for the file; just make the entry normally */
X
X      if(args->size)`009`009`009/* should the size be included?`009      */
X      `123
X`009 /* no; there is a special case for the size because it is
X`009  * used as an integer instead as a string like the protection
X`009  * string; if the user did not want the date or the protection
X`009  * string, they will have null characters ('\0') in them and thus
X`009  * won't effect the sprintf() call; however, we can't make sprintf
X`009  * ignore integers even though they might contain 0
X`009  */
X
X`009 sprintf(buf,"%s %6d %s %s %s",ent->scr_name,ent->size,ent->date_str,
X`009`009 ent->prot_str,text_ptr);
X      `125
X      else
X      `123
X`009 sprintf(buf,"%s %s %s %s",ent->scr_name,ent->date_str,ent->prot_str,
X`009`009 text_ptr);
X      `125
X
X      return(0);`009`009`009/* return from here`009`009      */
X   `125
X   else
X   `123
X      /* there are some commands associated with this file; the slot
X       * should reflect this and it should be written in reverse video
X       */
X
X      ptr = ent->command;`009`009/* get pointer to command structure   */
X
X      if(ptr->comm_del)`009`009`009/* is the file going to be deleted?   */
X      `123
X`009 /* yes, now see if there is enough room to put in the "<delete>"
X`009  * string
X`009  */
X
X`009 if(slot_width <= (NAME_MAX + SIZE_MAX + 2))
X`009 `123
X`009    /* the slot is only big enough to use <del> to signify that the
X`009     * file is marked for deletion
X`009     */
X
X`009    sprintf(buf,"%-14.14s <del>       ",ent->scr_name);
X`009 `125
X`009 else
X`009 `123
X`009    /* use the regular "<delete>" string to show that the user
X`009     * marked the file to be deleted
X`009     */
X
X`009    sprintf(buf,"%s <delete>                                         \
X                                    ",ent->scr_name);
X`009 `125
X
X`009 *(buf + slot_width) = '\0';`009/* trim it to where it should be      */
X      `125
X      else
X      `123
X`009 /* no the file is not going to be deleted but it might have some other
X`009  * command associated with it; check them to be sure
X`009  */
X
X`009 if(args->prot)
X`009 `123
X`009    if(ptr->comm_prot)
X`009    `123
X`009       /* new protection string; format it */
X
X`009       prot_val_to_str(ptr->prot,prot_buf);
X`009       prot_ptr = prot_buf;
X`009    `125
X`009    else
X`009       prot_ptr = ent->prot_str; /* use the old protection string     */
X`009 `125
X`009 else
X`009    prot_ptr = nullptr;`009`009/* no string; make sure it is null    */
X
X`009 /* which text descriptor pointer should we use? */
X
V`009 if(text_flag == DISPLAY_TEXT)`009/* should we display text descriptor? *
X/
X`009 `123
X`009    /* yes, text descriptors are to be displayed on the screen; now
X`009     * determine which, if any, text descriptor to use for the
X`009     * current file
X`009     */
X
X`009    if(ptr->text != NULL)`009/* use new text descriptor?`009      */
X`009    `123
X`009       /* use the new text descriptor for the slot */
X
X`009       cat(text_buf,ptr->text,blnk_text);
X`009       text_buf[TEXT_MAX] = '\0'; /* only use as much as we need      */
X`009       text_ptr = text_buf;`009/* set the pointer to the text desc.  */
X`009    `125
X`009    else if(ent->text != nullptr) /* or should we use the original?   */
X`009    `123
X`009       /* use the original text descriptor for the file */
X
X`009       cat(text_buf,ent->text,blnk_text);
X`009       text_buf[TEXT_MAX] = '\0'; /* only use as much as we need      */
X`009       text_ptr = text_buf;`009/* set the pointer to the text desc.  */
X`009    `125
X`009    else`009`009`009/* or should we use a blank desc?     */
X`009    `123
X`009       /* this file has no text descriptor; use a blank one to make
X`009`009* sure that we completely write over any text descriptor that
X`009`009* might been written in the current slot before this
-+-+-+-+-+ End of part 8 +-+-+-+-+-

