	        /*********************************
		 *                               *
		 *   Visual Shell v1.17  10/92   *
		 *                               *
		 *     by Torsten Jürgeleit      *
		 *                               *
		 *        display part 1         *
		 *                               *
		 *********************************/

	/* Includes */

#include "includes.h"
#include "imports.h"
#include "protos.h"

	/* Prepare console window for VSh */

   VOID
prepare_con_window(VOID)
{
   struct FileRequest  *freq1 = &file_req[0], *freq2 = &file_req[1];

   clear_input_line();
   FPrintf(con_handle, "\x9bx\x9by\x9bu\x9bt\x0c");   /* control back to console device */
   max_line_len     = (vsh_width - BORDER_LEFT - BORDER_RIGHT) / 8;   /* calc VSh dimensions */
   max_dir_name_len = ((vsh_width / 2) - 4 * 2) / 8;
   cli_vpos         = BORDER_TOP_SHOW;
   fkey_dist        = (vsh_width - BORDER_LEFT - BORDER_RIGHT - 2) /
					       MAX_FKEYS - MAX_FKEY_LEN * 8;
   fkey_left        = (vsh_width - MAX_FKEYS * MAX_FKEY_LEN * 8 - (MAX_FKEYS
						      - 1) * fkey_dist) / 2;

   move_and_resize_window(con_window, vsh_left, vsh_top, vsh_width,
								vsh_height);
   Delay(20L);
   WindowLimits(con_window, (LONG)vsh_width, (LONG)vsh_height, (LONG)
					       vsh_width, (LONG)vsh_height);
   con_window->BorderLeft   = BORDER_LEFT;   /* change size of inner window */
   con_window->BorderRight  = BORDER_RIGHT;
   con_window->BorderBottom = BORDER_BOTTOM;
   con_window->GZZWidth     = vsh_width - BORDER_LEFT - BORDER_RIGHT;

   SPrintf(&status_fmt[0],   /* init strings and structures which depends on VSh dimension */
		 "Chip %%7ld / %%-7ld Fast %%7ld / %%-7ld %%9s %%9s %%-%ds",
							 max_line_len - 69);
   SPrintf(&standard_fmt[0], "%%-%ds", max_line_len);

   freq1->fr_Display.d_LeftEdge          = (vsh_width / 2 -
						   MAX_FREQ_LINE_WIDTH) / 2;
   freq2->fr_Display.d_LeftEdge          = vsh_width -
			 freq1->fr_Display.d_LeftEdge - MAX_FREQ_LINE_WIDTH;
   freq1->fr_Display.d_TopEdge           = BORDER_TOP + STATUS_HEIGHT +
							DIR_NAME_HEIGHT + 1;
   freq2->fr_Display.d_TopEdge           = BORDER_TOP + STATUS_HEIGHT +
							DIR_NAME_HEIGHT + 1;
   freq1->fr_Display.d_VisibleLines      = (cli_vpos - INFO_LINE_HEIGHT -
					   freq1->fr_Display.d_TopEdge) / 8;
   freq2->fr_Display.d_VisibleLines      = (cli_vpos - INFO_LINE_HEIGHT -
					   freq2->fr_Display.d_TopEdge) / 8;
   freq1->fr_Display.d_TopEdge          += ((cli_vpos - INFO_LINE_HEIGHT -
				      freq1->fr_Display.d_TopEdge) % 8) / 2;
   freq2->fr_Display.d_TopEdge          += ((cli_vpos - INFO_LINE_HEIGHT -
				      freq2->fr_Display.d_TopEdge) % 8) / 2;
   view_req.vr_Display.d_TopEdge         = BORDER_TOP_HIDDEN;
   view_req.vr_Display.d_Width           = max_line_len * 8;
   view_req.vr_Display.d_VisibleLines    = (cli_vpos -
				     view_req.vr_Display.d_TopEdge - 2) / 8;
   view_req.vr_Display.d_TopEdge        += ((cli_vpos -
				view_req.vr_Display.d_TopEdge - 2) % 8) / 2;
   history_req.hr_Display.d_TopEdge      = BORDER_TOP_HIDDEN;
   history_req.hr_Display.d_Width        = max_line_len * 8;
   history_req.hr_Display.d_VisibleLines = (cli_vpos -
				  history_req.hr_Display.d_TopEdge - 2) / 8;
   history_req.hr_Display.d_TopEdge     += ((cli_vpos -
			     history_req.hr_Display.d_TopEdge - 2) % 8) / 2;
   tree_req.tr_Display.d_TopEdge         = BORDER_TOP_HIDDEN;
   tree_req.tr_Display.d_Width           = max_line_len * 8;
   tree_req.tr_Display.d_VisibleLines    = (cli_vpos -
				     tree_req.tr_Display.d_TopEdge - 2) / 8;
   tree_req.tr_Display.d_TopEdge        += ((cli_vpos -
				tree_req.tr_Display.d_TopEdge - 2) % 8) / 2;
   tree_req.tr_Columns                   = (max_line_len - 1) /
					       (MAX_TREE_NODE_NAME_LEN + 3);
   tree_req.tr_Rows                      = tree_req.tr_Display.d_VisibleLines;

   move_freq_cursor(freq1, get_file_node_under_cursor(freq1),
						       MOVE_MODE_NO_OUTPUT);
   move_freq_cursor(freq2, get_file_node_under_cursor(freq2),
						       MOVE_MODE_NO_OUTPUT);
}
	/* Restore old console window */

   VOID
restore_con_window(VOID)
{
   con_window->BorderLeft   = old_bleft;   /* restore old window dimensions */
   con_window->BorderRight  = old_bright;
   con_window->BorderTop    = old_btop;
   con_window->BorderBottom = old_bbottom;
   con_window->Flags        = old_flags;
   RefreshWindowFrame(con_window);
   WindowLimits(con_window, (LONG)old_min_width, (LONG)old_min_height,
				 (LONG)old_max_width, (LONG)old_max_height);
   move_and_resize_window(con_window, old_left, old_top, old_width,
								old_height);
   clear_input_line();
   FPrintf(con_handle, "\x9bx\x9by\x9bu\x9bt\x0c");   /* control back to console device */
}
	/* Move and resize window to selected dimension */

   VOID
move_and_resize_window(struct Window *win, USHORT new_left, USHORT new_top,
					USHORT new_width, USHORT new_height)
{
   SHORT move_x = (SHORT)new_left - win->LeftEdge,
	 move_y = (SHORT)new_top - win->TopEdge,
	 size_x = (SHORT)new_width - win->Width,
	 size_y = (SHORT)new_height - win->Height;

   if (size_x < 0) {   /* zoom width in */
      if (size_x) {
	 SizeWindow(con_window, (LONG)size_x, 0L);
      }
      if (move_x) {
	 MoveWindow(con_window, (LONG)move_x, 0L);
      }
   } else {   /* zoom width out */
      if (move_x) {
	 MoveWindow(con_window, (LONG)move_x, 0L);
      }
      if (size_x) {
	 SizeWindow(con_window, (LONG)size_x, 0L);
      }
   }
   if (size_y < 0) {   /* zoom height in */
      if (size_y) {
	 SizeWindow(con_window, 0L, (LONG)size_y);
      }
      if (move_y) {
	 MoveWindow(con_window, 0L, (LONG)move_y);
      }
   } else {   /* zoom height out */
      if (move_y) {
	 MoveWindow(con_window, 0L, (LONG)move_y);
      }
      if (size_y) {
	 SizeWindow(con_window, 0L, (LONG)size_y);
      }
   }
}
	/* Init structures and start VSh */

   VOID
start_vsh(VOID)
{
   struct Gadget       *gad = &gadget;
   struct StringInfo   *si = &gadget_info;
   struct IntuiText    *it = &gadget_text;
   struct DateTime     *dat = &date_time;
   struct FileRequest  *freq1 = &file_req[0], *freq2 = &file_req[1];
   SHORT error;

   /* Init some flags */
   event_mode   = EVENT_MODE_IGNORE;
   action       = VSH_ACTION_NONE;
   auto_repeat  = 0;
   active_freq  = 0;
   scroll_flag  = 0;
   num_lock     = 1;
   qualifier    = QUALIFIER_NONE;
   enable_abort = 0;
   delayed_cd   = 0;

   status       = VSH_STATUS_NORMAL;
   status_delay = DEFAULT_STATUS_DELAY;
   error_delay  = DEFAULT_ERROR_DELAY;

   /* Init requesters */
   freq1->fr_Display.d_Mode          = DISPLAY_MODE_FILE;
   freq2->fr_Display.d_Mode          = DISPLAY_MODE_FILE;
   freq1->fr_Display.d_Width         = MAX_FREQ_LINE_WIDTH;
   freq2->fr_Display.d_Width         = MAX_FREQ_LINE_WIDTH;
   freq1->fr_CursorLine              = -1;
   freq2->fr_CursorLine              = -1;
   freq1->fr_AnchorPath.ap_BreakBits = 0;   /* no abort */
   freq2->fr_AnchorPath.ap_BreakBits = 0;
   freq1->fr_AnchorPath.ap_StrLen    = 0;   /* basename only */
   freq2->fr_AnchorPath.ap_StrLen    = 0;
   strcpy(&freq1->fr_FilePattern[0], DEFAULT_FILE_PATTERN);
   strcpy(&freq2->fr_FilePattern[0], DEFAULT_FILE_PATTERN);
   strcpy(&freq1->fr_MarkPattern[0], DEFAULT_MARK_PATTERN);
   strcpy(&freq2->fr_MarkPattern[0], DEFAULT_MARK_PATTERN);
   strcpy(&freq1->fr_UnmarkPattern[0], DEFAULT_UNMARK_PATTERN);
   strcpy(&freq2->fr_UnmarkPattern[0], DEFAULT_UNMARK_PATTERN);
   view_req.vr_Display.d_Mode        = DISPLAY_MODE_VIEW;
   view_req.vr_Display.d_LeftEdge    = BORDER_LEFT;
   history_req.hr_Display.d_Mode     = DISPLAY_MODE_HISTORY;
   history_req.hr_Display.d_LeftEdge = BORDER_LEFT;
   tree_req.tr_Display.d_Mode        = DISPLAY_MODE_TREE;
   tree_req.tr_Display.d_LeftEdge    = BORDER_LEFT;

   /* Init gadget struct */
   gad->NextGadget    = NULL;
   gad->Flags         = GADGHCOMP;
   gad->GadgetType    = STRGADGET;
   gad->GadgetRender  = NULL;
   gad->SelectRender  = NULL;
   gad->GadgetText    = it;
   gad->MutualExclude = 0L;
   gad->SpecialInfo   = (APTR)si;
   gad->GadgetID      = 0;
   gad->UserData      = NULL;

   /* Init gadget text struct */
   it->FrontPen  = COLOR3;
   it->BackPen   = COLOR0;
   it->DrawMode  = JAM2;
   it->TopEdge   = 0;
   it->ITextFont = &topaz80;
   it->NextText  = NULL;

   /* Init gadget string info struct */
   si->Buffer     = (UBYTE *)&gadget_buffer[0];
   si->UndoBuffer = NULL;
   si->UndoPos    = 0;
   si->NumChars   = MAX_GADGET_BUFFER_LEN;
   si->AltKeyMap  = NULL;

   /* Init DateTime struct */
   dat->dat_Format  = 0;
   dat->dat_Flags   = FORMAT_DOS;
   dat->dat_StrDay  = &day_buffer[0];
   dat->dat_StrDate = &date_buffer[0];
   dat->dat_StrTime = &time_buffer[0];

   /* Build display and start action */
   draw_display(FULL_DISPLAY);
   if (!dir_arg[0] && !dir_arg[1] && show_flag) {
      event_mode = EVENT_MODE_NORMAL;
      action_about();
      event_mode = EVENT_MODE_IGNORE;
   }
   if ((error = read_new_dir(freq1, dir_arg[0], READ_DIR_MODE_NO_OUTPUT)) ==
							VSH_STATUS_NORMAL) {
      if (!Strcmp(dir_arg[0], dir_arg[1])) {
	 error = duplicate_file_list(freq1, freq2);
      } else {
	 error = read_new_dir(freq2, dir_arg[1], READ_DIR_MODE_NO_OUTPUT);
      }
   }
   status = error;

   draw_requesters(DRAW_MODE_NORMAL);
   perform_action();
   clear_display(FULL_DISPLAY);

   free_dir(freq1);
   free_dir(freq2);
}
	/* Draw VSh display */

   VOID
draw_display(USHORT mode)
{
   clear_input_line();
   FPrintf(con_handle, cursor_off);   /* home & cursor off */
   SetAPen(con_rport, (LONG)COLOR0);   /* clear console window */
   if (mode == FULL_DISPLAY) {
      if (! show_flag) {   /* hidden display -> config */
	 con_window->GZZHeight = vsh_height - BORDER_TOP_HIDDEN -
						   con_window->BorderBottom;
	 FPrintf(con_handle, "\x9b%dx\x9b%dy\x9b%du\x9b%dt\x9bH",
	    BORDER_LEFT, BORDER_TOP_HIDDEN, max_line_len, HIDDEN_CLI_LINES);
      } else {
	 con_window->GZZHeight = SHOW_CLI_HEIGHT;
         FPrintf(con_handle, "\x9b%dx\x9b%dy\x9b%du\x9b%dt\x9bH",
		       BORDER_LEFT, cli_vpos, max_line_len, SHOW_CLI_LINES);
      }
      RectFill(con_rport, (LONG)(BORDER_LEFT - 2), (LONG)(BORDER_TOP - 1),
	      (LONG)(vsh_width - BORDER_RIGHT + 1), (LONG)(vsh_height - 2));
      if (! show_flag) {   /* hidden display -> config */
	 draw_line(COLOR1, (USHORT)2, (USHORT)(BORDER_TOP_HIDDEN - 2),
		  (USHORT)(vsh_width - 3), (USHORT)(BORDER_TOP_HIDDEN - 2));
      }
      draw_line(COLOR1, (USHORT)2, (USHORT)(vsh_height - FKEY_HEIGHT),
	       (USHORT)(vsh_width - 3), (USHORT)(vsh_height - FKEY_HEIGHT));
   } else {
      if (! show_flag) {   /* hidden display -> help */
	 con_window->GZZHeight = vsh_height - BORDER_TOP_HIDDEN -
						   con_window->BorderBottom;
	 FPrintf(con_handle, "\x9b%dx\x9b%dy\x9b%du\x9b%dt\x9bH",
	    BORDER_LEFT, BORDER_TOP_HIDDEN, max_line_len, HIDDEN_CLI_LINES);
	 RectFill(con_rport, (LONG)(BORDER_LEFT - 2), (LONG)BORDER_TOP,
		     (LONG)(vsh_width - BORDER_RIGHT + 1), (LONG)(vsh_height
							- FKEY_HEIGHT - 1));
	 draw_line(COLOR1, (USHORT)2, (USHORT)(BORDER_TOP_HIDDEN - 2),
		  (USHORT)(vsh_width - 3), (USHORT)(BORDER_TOP_HIDDEN - 2));
      } else {
	 con_window->GZZHeight = SHOW_CLI_HEIGHT;
	 FPrintf(con_handle, "\x9b%dx\x9b%dy\x9b%du\x9b%dt\x9bH",
		       BORDER_LEFT, cli_vpos, max_line_len, SHOW_CLI_LINES);
	 RectFill(con_rport, (LONG)(BORDER_LEFT - 2), (LONG)
		    BORDER_TOP_HIDDEN, (LONG)(vsh_width - BORDER_RIGHT + 1),
				      (LONG)(vsh_height - FKEY_HEIGHT - 1));
      }
   }
   draw_requesters(DRAW_MODE_NORMAL);
   FPrintf(con_handle, cursor_on);   /* home & cursor on */
}
	/* Refresh VSh display */

   VOID
refresh_display(VOID)
{
   if (! show_flag) {   /* hidden display ? */
      draw_line(COLOR1, (USHORT)2, (USHORT)(BORDER_TOP_HIDDEN - 2), (USHORT)
			  (vsh_width - 3), (USHORT)(BORDER_TOP_HIDDEN - 2));
   }
   draw_line(COLOR1, (USHORT)2, (USHORT)(vsh_height - FKEY_HEIGHT), (USHORT)
		       (vsh_width - 3), (USHORT)(vsh_height - FKEY_HEIGHT));
   draw_requesters(DRAW_MODE_NORMAL);
}
	/* Clear VSh display */

   VOID
clear_display(USHORT mode)
{
   clear_input_line();
   FPrintf(con_handle, cursor_off);   /* home & cursor off */
   SetAPen(con_rport, (LONG)COLOR0);   /* clear console window */
   if (mode == FULL_DISPLAY) {
      RectFill(con_rport, (LONG)(BORDER_LEFT - 2), (LONG)BORDER_TOP, (LONG)
		    (vsh_width - BORDER_RIGHT + 1), (LONG)(vsh_height - 2));
   } else {
      if (! show_flag) {   /* hidden display -> help */
	 con_window->GZZHeight = SHOW_CLI_HEIGHT;
	 FPrintf(con_handle, "\x9b%dx\x9b%dy\x9b%du\x9b%dt\x9bH",
		       BORDER_LEFT, cli_vpos, max_line_len, SHOW_CLI_LINES);
	 RectFill(con_rport, (LONG)(BORDER_LEFT - 2), (LONG)BORDER_TOP,
		   (LONG)(vsh_width - BORDER_RIGHT + 1), (LONG)(vsh_height -
							  FKEY_HEIGHT - 1));
	 draw_line(COLOR1, (USHORT)2, (USHORT)(cli_vpos - 2), (USHORT)
				   (vsh_width - 3), (USHORT)(cli_vpos - 2));
      } else {
	 con_window->GZZHeight = vsh_height - BORDER_TOP_HIDDEN -
						   con_window->BorderBottom;
	 FPrintf(con_handle, "\x9b%dx\x9b%dy\x9b%du\x9b%dt\x9bH",
	    BORDER_LEFT, BORDER_TOP_HIDDEN, max_line_len, HIDDEN_CLI_LINES);
	 RectFill(con_rport, (LONG)(BORDER_LEFT - 2), (LONG)
		  (BORDER_TOP_HIDDEN - 1), (LONG)(vsh_width - BORDER_RIGHT +
				  1), (LONG)(vsh_height	- FKEY_HEIGHT - 1));
	 draw_line(COLOR1, (USHORT)2, (USHORT)(BORDER_TOP_HIDDEN - 2),
		  (USHORT)(vsh_width - 3), (USHORT)(BORDER_TOP_HIDDEN - 2));
      }
   }
   FPrintf(con_handle, cursor_on);   /* home & cursor on */
}
	/* Draw both file requesters */

   VOID
draw_requesters(USHORT mode)
{
   struct FileRequest  *freq1 = &file_req[0], *freq2 = &file_req[1];

   if (mode == DRAW_MODE_CLEAR) {
      SetAPen(con_rport, (LONG)COLOR0);
      RectFill(con_rport, (LONG)(BORDER_LEFT - 2), (LONG)BORDER_TOP, (LONG)
		      (vsh_width - BORDER_RIGHT + 1), (LONG)(cli_vpos - 3));
   }
   if (show_flag) {   /* hidden display ? */
      mark_active_freq();
      print_dir_name(freq1, (BYTE *)NULL);
      print_dir_name(freq2, (BYTE *)NULL);
      draw_line(COLOR1, (USHORT)(vsh_width / 2 - 1), (USHORT)
	      (BORDER_TOP_HIDDEN - 2), (USHORT)(vsh_width / 2 - 1), (USHORT)
					     (cli_vpos - INFO_LINE_HEIGHT));
      draw_line(COLOR1, (USHORT)(vsh_width / 2), (USHORT)(BORDER_TOP_HIDDEN
			  - 2), (USHORT)(vsh_width / 2), (USHORT)(cli_vpos -
							 INFO_LINE_HEIGHT));
      draw_line(COLOR1, (USHORT)2, (USHORT)(cli_vpos - INFO_LINE_HEIGHT),
	    (USHORT)(vsh_width - 3), (USHORT)(cli_vpos - INFO_LINE_HEIGHT));
      draw_line(COLOR1, (USHORT)2, (USHORT)(cli_vpos - 2), (USHORT)
				   (vsh_width - 3), (USHORT)(cli_vpos - 2));
   
      print_freq_lines(freq1, freq1->fr_Display.d_FirstVisibleNode, (USHORT)
				       0, freq1->fr_Display.d_VisibleLines);
      print_freq_lines(freq2, freq2->fr_Display.d_FirstVisibleNode, (USHORT)
				       0, freq2->fr_Display.d_VisibleLines);
      hcomp_freq_cursor(&file_req[active_freq]);
      print_info_line(INFO_LINE_MODE_NORMAL);
   }
   change_fkey_text();
   print_status(status);
}
	/* Draw line on console window */

   VOID
draw_line(USHORT color, USHORT x1, USHORT y1, USHORT x2, USHORT y2)
{
   SetAPen(con_rport, (LONG)color);
   Move(con_rport, (LONG)x1, (LONG)y1);
   Draw(con_rport, (LONG)x2, (LONG)y2);
}
	/* Mark directory name of active file requester */

   VOID
mark_active_freq(VOID)
{
   USHORT old_x1, old_x2, new_x1, new_x2;

   if (show_flag) {   /* hidden display ? */
      if (! active_freq) {
	 old_x1 = vsh_width / 2 + 1;
	 old_x2 = vsh_width - 3;
	 new_x1 = 2;
	 new_x2 = vsh_width / 2 - 1;
      } else {
	 old_x1 = 2;
	 old_x2 = vsh_width / 2 - 1;
	 new_x1 = vsh_width / 2 + 1;
	 new_x2 = vsh_width - 3;
      }
      draw_line(COLOR1, old_x1, (USHORT)(BORDER_TOP_HIDDEN - 2), old_x2,
					   (USHORT)(BORDER_TOP_HIDDEN - 2));
      draw_line(COLOR1, old_x1, (USHORT)(BORDER_TOP_HIDDEN + 9), old_x2,
					   (USHORT)(BORDER_TOP_HIDDEN + 9));
      draw_line(COLOR3, new_x1, (USHORT)(BORDER_TOP_HIDDEN - 2), new_x2,
					   (USHORT)(BORDER_TOP_HIDDEN - 2));
      draw_line(COLOR3, new_x1, (USHORT)(BORDER_TOP_HIDDEN + 9), new_x2,
					   (USHORT)(BORDER_TOP_HIDDEN + 9));
   }
}
	/* Print status line for file requester */

   VOID
print_status(SHORT error)
{
   struct DateTime  *dat = &date_time;
   BYTE *line = &line2_buffer[0];

   if (error == VSH_STATUS_NORMAL) {

      /* Print status line with available memory, actual date and time */
      if (num_lock) {
	 display_text(COLOR2, COLOR3, (USHORT)(BORDER_LEFT + (max_line_len -
						3) * 8), BORDER_TOP, "Num");
      } else {
	 display_text(COLOR1, COLOR0, (USHORT)(BORDER_LEFT + (max_line_len -
						3) * 8), BORDER_TOP, "   ");
      }
      DateStamp(&dat->dat_Stamp);
      StamptoStr(dat);
      SPrintf(line, &status_fmt[0], AvailMem(MEMF_CHIP),
		    AvailMem(MEMF_CHIP | MEMF_LARGEST), AvailMem(MEMF_FAST),
		    AvailMem(MEMF_FAST | MEMF_LARGEST), &dat->dat_StrDay[0],
				&dat->dat_StrDate[0], &dat->dat_StrTime[0]);
      status_delay = DEFAULT_STATUS_DELAY;
   } else {
      if (error > 0) {

	 /* Print status */
	 SPrintf(line, &standard_fmt[0], status_text[error - 1]);
      } else {

	 /* Print error */
	 SPrintf(line, &standard_fmt[0], error_text[(-error) - 1]);
	 error_delay = DEFAULT_ERROR_DELAY;
      }
   }
   display_text(COLOR3, COLOR0, BORDER_LEFT, BORDER_TOP, line);
   status = error;   /* save last error code */
}
	/* Print dos status line */

   VOID
print_dos_status(USHORT mode, BYTE *source, BYTE *dest)
{
   BYTE   *ptr, *buffer = &line2_buffer[0];
   USHORT text_len, path_len, max_len;

   /* Get leading text */
   switch(mode) {
      case DOS_MODE_COPY :
	 ptr = "Copying ";
	 break;
      case DOS_MODE_RENAME :
	 ptr = "Renaming ";
	 break;
      case DOS_MODE_DELETE :
	 ptr = "Deleting ";
	 break;
      case DOS_MODE_FIND :
	 ptr = "Found ";
	 break;
      case DOS_MODE_TREE :
	 ptr = "Scanning ";
	 break;
      default :
	 ptr = "";
	 break;
   }

   /* Calc maximal length for path names */
   text_len = strlen(ptr);
   max_len  = max_line_len - text_len;
   if (dest) {
      max_len -= 4;
      path_len = max_len / 2;
   } else {
      path_len = max_len;
   }

   /* Build and print status line */
   strcpy(buffer, ptr);
   ptr = buffer + text_len;

   if (!dest) {

      /* Append source path */
      build_limited_path_name(ptr, NULL, source, path_len,
						    LIMITED_PATH_MODE_FILL);
   } else {

      /* Append source path */
      build_limited_path_name(ptr, NULL, source, path_len,
						  LIMITED_PATH_MODE_NORMAL);
      /* Search end of source name */
      path_len = strlen(ptr);
      ptr     += path_len;

      /* Append destination path */
      strcpy(ptr, " to ");
      ptr += 4;
      build_limited_path_name(ptr, NULL, dest, max_len - path_len,
						    LIMITED_PATH_MODE_FILL);
   }
   display_text(COLOR3, COLOR0, BORDER_LEFT, BORDER_TOP, buffer);
}
	/* Print status line for view requester */

   VOID
print_vreq_status(struct ViewRequest  *vreq)
{
   struct Display  *vd = &vreq->vr_Display;
   ULONG  num_entries = vd->d_NumEntries,
	  pos = ((struct LineNode *)vd->d_FirstVisibleNode)->ln_Pos;
   BYTE   *line = &line2_buffer[0];
   USHORT i, vlines = vd->d_VisibleLines;

   SPrintf(line, "Viewing \"%s\"   %ld bytes   line %ld of %ld   %ld%%",
		   vreq->vr_FileName, vreq->vr_BufferSize, pos, num_entries,
	  (num_entries > vlines ? ((pos + vlines - 1) * 100) / num_entries :
								     100L));
   for (i = strlen(line); i < max_line_len; i++) {   /* fill string spaces */
      *(line +i) = ' ';
   }
   *(line + max_line_len) = '\0';
   display_text(COLOR3, COLOR0, BORDER_LEFT, BORDER_TOP, line);
}
	/* Print status line for tree requester */

   VOID
print_treq_status(struct TreeRequest  *treq)
{
   BYTE *path;

   path = build_tnode_path_name(treq, treq->tr_CursorNode);
   print_dos_status(DOS_MODE_NORMAL, path, NULL);
}
	/* Print directory name of specified filerequester */

   VOID
print_dir_name(struct FileRequest  *freq, BYTE *dir)
{
   BYTE *path, *buffer = &line2_buffer[0];

   if (show_flag) {   /* hidden display ? */
      if (!dir) {
	 path = &path1_buffer[0];
	 strcpy(path, &freq->fr_DirName[0]);
	 if (*path != '\0') {
	    TackOn(path, &freq->fr_FilePattern[0]);   /* attach pattern to dir name */
	 }
      } else {
	 path = dir;
      }
      build_limited_path_name(buffer, NULL, path, max_dir_name_len,
						      LIMITED_PATH_MODE_FILL);
      if (freq->fr_Display.d_LeftEdge >= (vsh_width / 2)) {
	 display_text(COLOR1, COLOR2, (USHORT)(vsh_width / 2 + 4),
						   BORDER_TOP_HIDDEN, buffer);
      } else {
	 display_text(COLOR1, COLOR2, BORDER_LEFT, BORDER_TOP_HIDDEN, buffer);
      }
   }
}
	/* Print directory name of specified filerequester */

   VOID
print_info_line(USHORT mode)
{
   struct FileRequest  *freq1 = &file_req[active_freq],
		       *freq2 = (freq1 == &file_req[0] ? &file_req[1] :
							      &file_req[0]);
   struct FileNode     *fnode;
   BYTE   *line = &line2_buffer[0];
   USHORT i;

   if (show_flag) {
      if (mode != INFO_LINE_MODE_EMPTY && (freq1->fr_Mode ==
		       FREQ_MODE_NORMAL || freq1->fr_Mode == FREQ_MODE_FIND)
					    && freq1->fr_CursorLine != -1) {
	 fnode = get_file_node_under_cursor(freq1);
	 if (freq1->fr_Mode == FREQ_MODE_FIND && fnode->fn_Path) {
	    print_dir_name(freq1, fnode->fn_Path);
	 }
	 if (!freq1->fr_MarkedEntries) {
	    if (mode == INFO_LINE_MODE_MARKED) {
	       *line = '\0';   /* empty info line */
	    } else {
	       CopyMem((BYTE *)&fnode->fn_Date, (BYTE *)
		      &date_time.dat_Stamp, (LONG)sizeof(struct DateStamp));
	       StamptoStr(&date_time);
	       SPrintf(line, "%s %s %9s %9s %-s",
				      &fnode->fn_Text[0], protection(fnode),
			&date_time.dat_StrDay[0], &date_time.dat_StrDate[0],
						 &date_time.dat_StrTime[0]);
	    }
	 } else {
	    SPrintf(line, "%ld entries with %ld bytes selected",
			     freq1->fr_MarkedEntries, freq1->fr_MarkedSize);
	 }
      } else {
	 *line = '\0';   /* empty info line */
      }
      for (i = strlen(line); i < max_line_len; i++) {   /* fill rest of line with spaces */
	 *(line + i) = ' ';
      }
      *(line + i) = '\0';
      display_text(COLOR1, COLOR0, BORDER_LEFT, INFO_LINE_VPOS, line);
      if (mode == INFO_LINE_MODE_NORMAL && freq2->fr_Mode ==
						     FREQ_MODE_QUICK_VIEW) {
	 print_quick_view(freq2);
      }
   }
}
	/* Print text for function keys */

   VOID
print_fkey_text(USHORT mode)
{
   BYTE   *line = &line2_buffer[0], **fkey;
   USHORT i;

   if (mode == FKEY_MODE_NORMAL) {
      switch (qualifier) {   /* check qualifier and change fkey text if required */
	 case QUALIFIER_NONE :
	    break;
	 case QUALIFIER_SHIFT :
	    switch (file_req[active_freq].fr_Mode) {
	       case FREQ_MODE_NORMAL :
		  mode = FKEY_MODE_SHIFT_NORMAL;
		  break;
	       case FREQ_MODE_DEVS_ASN :
		  mode = FKEY_MODE_SHIFT_DEVS_ASN;
		  break;
	       case FREQ_MODE_INFO :
		  mode = FKEY_MODE_SHIFT_INFO;
		  break;
	       case FREQ_MODE_QUICK_VIEW :
		  mode = FKEY_MODE_SHIFT_QUICK_VIEW;
		  break;
	       case FREQ_MODE_FIND :
		  mode = FKEY_MODE_SHIFT_FIND;
		  break;
	    }
	    break;
	 case QUALIFIER_ALT :
	 case QUALIFIER_SHIFT_ALT :
	    mode = FKEY_MODE_USER_FUNCS;
	    break;
	 default :
	    mode = FKEY_MODE_NONE;
	    break;
      }
   }
   if (mode == FKEY_MODE_USER_FUNCS) {
      fkey = &user_fkey_text[0];
   } else {
      fkey = &fkey_text[mode][0];
   }
   *line       = '0';
   *(line + 1) = '\0';
   for (i = 0; i < MAX_FKEYS; i++) {
      if (++(*line) > '9') {   /* calc function key number */
	 *line = '0';
      }
      display_text(COLOR1, COLOR0, (USHORT)(fkey_left + MAX_FKEY_LEN * 8 * i
	    + fkey_dist * i), (USHORT)(vsh_height - FKEY_HEIGHT + 2), line);
      display_text(COLOR2, COLOR3, (USHORT)(fkey_left +
	    MAX_FKEY_LEN * 8 * i + fkey_dist * i + 8), (USHORT)(vsh_height -
						 FKEY_HEIGHT + 2), *fkey++);
   }
}
	/* Print text left aligned on console window at specified position */

   VOID 
display_text_left(USHORT front_color, USHORT back_color, USHORT x, USHORT y,
						 BYTE *text, USHORT max_len)
{
   USHORT i, len = 0;

   if (! text) {
      line2_buffer[0] = '\0';
   } else {
      if ((len = strlen(text)) > max_len) {
	 strncpy(&line2_buffer[0], text, (size_t)max_len);
      } else {
	 strcpy(&line2_buffer[0], text);
      }
   }
   for (i = len; i < max_len; i++) {   /* fill string to <max_len> with spaces */
      line2_buffer[i] = ' ';
   }
   line2_buffer[max_len] = '\0';
   display_text(front_color, back_color, x, y, &line2_buffer[0]);
}
	/* Print text centered on console window at specified position */

   VOID
display_text_centered(USHORT front_color, USHORT back_color, USHORT x,
				       USHORT y, BYTE *text, USHORT max_len)
{
   BYTE   *ptr, *line = &line2_buffer[0];
   USHORT i, len;

   for (i = 0, ptr = line; i < max_len; i++) {   /* fill string with spaces */
      *ptr++ = ' ';
   }
   *ptr = '\0';
   if (text) {
      if ((len = strlen(text)) > max_len) {
	 strncpy(line, text, (size_t)max_len);
      } else {
	 strncpy(line + max_len / 2 - len / 2, text, (size_t)len);
      }
   }
   display_text(front_color, back_color, x, y, line);
}
	/* Change function keys related to the filerequester mode */

   VOID
change_fkey_text(VOID)
{
   if (! show_flag) {   /* hidden display ? */
      print_fkey_text(FKEY_MODE_HIDDEN);
   } else {
      print_fkey_text(FKEY_MODE_NORMAL);
   }
}
