		/*********************************
		 *                               *
		 *   Visual Shell v1.17  10/92   *
		 *                               *
		 *     by Torsten Jürgeleit      *
		 *                               *
		 *         action part 2         *
		 *                               *
		 *********************************/

	/* Includes */

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

	/* Get parent directory for active filerequester */

   VOID
action_parent_dir(VOID)
{
   struct FileRequest  *freq = &file_req[active_freq];
   BYTE  *base_name, *last_sub = &file1_buffer[0],
	 *dir_name = &path1_buffer[0];
   SHORT error;

   strcpy(dir_name, &freq->fr_DirName[0]);
   if (*dir_name != '\0') {   /* dirname != "" ? */

      /* Save directory we came from */
      if (*(base_name = BaseName(dir_name)) != '\0') {
	 strcpy(last_sub, base_name);
	 if (*(base_name - 1) == '/') {
	    base_name--;
	 }
	 *base_name = '\0';

	 /* Read parent directory and move cursor to last sub directory */
	 if ((error = read_new_dir(freq, dir_name, READ_DIR_MODE_NO_PRINT))
						     == VSH_STATUS_NORMAL) {
	    move_freq_cursor(freq, search_file_node((struct FileNode *)
				freq->fr_Display.d_List->mlh_Head, last_sub,
				(USHORT)strlen(last_sub)), MOVE_MODE_PRINT);
	    change_fkey_text();
	 }
	 print_status(error);
      }
   }
}
	/* Get root directory for active filerequester */

   VOID
action_root_dir(VOID)
{
   struct FileRequest  *freq = &file_req[active_freq];
   BYTE  *p, *base_name, *last_sub = &file1_buffer[0],
	 *dir_name = &path1_buffer[0];
   SHORT error;

   strcpy(dir_name, &freq->fr_DirName[0]);
   if (*dir_name != '\0') {   /* dirname != "" ? */

      /* Save directory we came from */
      if (p = strchr(dir_name, '/')) {
	 *p = '\0';
      }
      if (*(base_name = BaseName(dir_name)) != '\0') {
	 strcpy(last_sub, base_name);
	 *base_name = '\0';

	 /* Read root directory and move cursor to last sub directory */
	 if ((error = read_new_dir(freq, dir_name, READ_DIR_MODE_NO_PRINT))
						     == VSH_STATUS_NORMAL) {
	    move_freq_cursor(freq, search_file_node((struct FileNode *)
				freq->fr_Display.d_List->mlh_Head, last_sub,
				(USHORT)strlen(last_sub)), MOVE_MODE_PRINT);
	    change_fkey_text();
	 }
	 print_status(error);
      }
   }
}
	/* Get new directory from cursor line */

   VOID
action_new_dir(USHORT mode)
{
   struct FileRequest  *freq, *freq1 = &file_req[active_freq],
		       *freq2 = &file_req[(active_freq ? 0 : 1)];
   struct FileNode     *fnode;
   BYTE *dir_name = &path1_buffer[0];

   if (freq1->fr_Mode != FREQ_MODE_INFO && freq1->fr_Mode !=
		       FREQ_MODE_QUICK_VIEW && freq1->fr_CursorLine != -1) {
      fnode = get_file_node_under_cursor(freq1);
      if (freq1->fr_Mode == FREQ_MODE_DEVS_ASN || freq1->fr_Mode ==
		       FREQ_MODE_FIND || fnode->fn_Type == ENTRY_TYPE_DIR) {   /* device, assign or directory selected ? */
	 switch (freq1->fr_Mode) {
	    case FREQ_MODE_DEVS_ASN :
	       strncpy(dir_name, &fnode->fn_Text[0], (size_t)
							 fnode->fn_NameLen);
	       *(dir_name + fnode->fn_NameLen) = '\0';
	       break;
	    case FREQ_MODE_FIND :
	       strcpy(dir_name, fnode->fn_Path);
	       if (fnode->fn_Type == ENTRY_TYPE_DIR) {   /* dir ? */
		  append_base_name(dir_name, fnode);
	       }
	       break;
	    case FREQ_MODE_NORMAL :
	       strcpy(dir_name, &freq1->fr_DirName[0]);
	       append_base_name(dir_name, fnode);
	       break;
	 }
	 if (mode == NEW_DIR_MODE_TO_NONACTIVE) {
	    freq = freq2;   /* new dir to nonactive freq */
	 } else {
	    freq = freq1;   /* new dir to active freq */
	 }
	 print_status(read_new_dir(freq, dir_name, READ_DIR_MODE_NORMAL));
      }
   }
}
	/* Read the same directory once again */

   VOID
action_read_again(VOID)
{
   print_status(read_same_dir(&file_req[active_freq],
						READ_SAME_DIR_MODE_NORMAL));
}
	/* Run file, view file or enter directory from cursor line */

   VOID
action_enter(VOID)
{
   struct CommandLineInterface  *cli = BTOC(_parent_proc->pr_CLI);
   struct FileRequest  *freq = &file_req[active_freq];
   struct FileNode     *fnode;
   BYTE  *prog = &path1_buffer[0];
   BPTR  cd_lock;
   SHORT error = VSH_STATUS_NORMAL;

   if (cli == save_cli && freq->fr_Mode != FREQ_MODE_INFO && freq->fr_Mode
		     != FREQ_MODE_QUICK_VIEW && freq->fr_CursorLine != -1) {
      fnode = get_file_node_under_cursor(freq);
      if (freq->fr_Mode == FREQ_MODE_DEVS_ASN || fnode->fn_Type ==
							   ENTRY_TYPE_DIR) {   /* device, assign or directory selected ? */
	 action_new_dir(NEW_DIR_MODE_NORMAL);   /* enter selected directory */
      } else {   /* file selected */
	 if (fnode->fn_Protection & FIBF_SCRIPT) {   /* script file ? */
	    strcpy(prog, EXECUTE_NAME);
	    if (!append_path_name(prog + strlen(prog), freq, fnode,
						      APPEND_MODE_NORMAL)) {
	       error = VSH_ERROR_LOCK_FAILED;
	    } else {
	       print_status(VSH_STATUS_EXECUTE_SCRIPT);   /* execute selected script file */
	       action_display_mode();
	       print_fkey_text(FKEY_MODE_NONE);
	       error = force_string(prog, (USHORT)strlen(prog),
						 FORCE_MODE_NEWLINE_APPEND);
	       change_fkey_text();
	    }
	 } else {   /* no script file */
	    if (!append_path_name(prog, freq, fnode, APPEND_MODE_NORMAL)) {
	       error = VSH_ERROR_LOCK_FAILED;
	    } else {
	       if ((error = check_for_load_file(prog)) == VSH_STATUS_NORMAL) {
		  print_status(VSH_STATUS_RUN_FILE);   /* start selected file */
		  action_display_mode();
		  print_fkey_text(FKEY_MODE_NONE);
		  cd_lock = (BPTR)CurrentDir(freq->fr_DirLock);
		  error   = execute(prog, empty);
		  CurrentDir(cd_lock);
		  change_fkey_text();
	       } else {
		  if (error == VSH_ERROR_NO_LOAD_FILE) {
		     error = view_file(freq, fnode);   /* view selected file */
		  }
	       }
	    }
	 }
	 print_status(error);
      }
   }
}
	/* Insert file name into command line */

   VOID
action_force_base(VOID)
{
   struct FileRequest  *freq = &file_req[active_freq];
   struct FileNode     *fnode;

   if ((freq->fr_Mode == FREQ_MODE_NORMAL || freq->fr_Mode ==
			     FREQ_MODE_FIND) && freq->fr_CursorLine != -1) {
      print_status(VSH_STATUS_INSERT_FILE);
      fnode = get_file_node_under_cursor(freq);   /* insert base name of selected file */
      print_status(force_string(&fnode->fn_Text[0], (USHORT)
				 fnode->fn_NameLen, FORCE_MODE_NO_NEWLINE));
   }
}
	/* Insert file name with full path into command line */

   VOID
action_force_full(VOID)
{
   struct FileRequest  *freq = &file_req[active_freq];
   struct FileNode     *fnode;
   BYTE *buffer = &path1_buffer[0];

   if ((freq->fr_Mode == FREQ_MODE_NORMAL || freq->fr_Mode ==
			     FREQ_MODE_FIND) && freq->fr_CursorLine != -1) {
      print_status(VSH_STATUS_INSERT_FILE);
      fnode = get_file_node_under_cursor(freq);   /* insert full path name of selected file */
      if (freq->fr_Mode == FREQ_MODE_FIND) {
	 strcpy(buffer, fnode->fn_Path);
      } else {
	 strcpy(buffer, &freq->fr_DirName[0]);
      }
      append_base_name(buffer, fnode);
      print_status(force_string(buffer, (USHORT)strlen(buffer),
						    FORCE_MODE_NO_NEWLINE));
   }
}
	/* Toggle num lock */

   VOID
action_num_lock(VOID)
{
   if (num_lock) {   /* clear num lock */
      num_lock = 0;
   } else {   /* set num lock */
      num_lock = 1;
   }
}
	/* Change file search pattern for active file requester */

   VOID
action_search_pattern(VOID)
{
   struct FileRequest  *freq = &file_req[active_freq];
   BYTE  *pattern_text, *default_input = &freq->fr_FilePattern[0];
   SHORT error = VSH_STATUS_NORMAL;

   if (pattern_text = get_input(INPUT_MODE_FILE_PATTERN, default_input)) {
      if (strlen(pattern_text) > MAX_PATTERN_LEN ||
			PreParse(pattern_text, &line1_buffer[0]) == FALSE) {
	 error = VSH_ERROR_INVALID_PATTERN;
      } else {
	 strcpy(default_input, pattern_text);   /* save new pattern */
	 error = read_same_dir(freq, READ_SAME_DIR_MODE_NORMAL);
      }
   }
   print_status(error);
}
	/* Mark or unmark selected entry in active file requester */

   VOID
action_mark_file(VOID)
{
   struct FileRequest  *freq = &file_req[active_freq];
   struct FileNode     *fnode;

   if ((freq->fr_Mode == FREQ_MODE_NORMAL || freq->fr_Mode ==
			     FREQ_MODE_FIND) && freq->fr_CursorLine != -1) {
      fnode = get_file_node_under_cursor(freq);
      if (fnode->fn_Marked) {   /* toggle mark */
	 fnode->fn_Marked     = 0;
	 freq->fr_MarkedSize -= fnode->fn_Size;
	 freq->fr_MarkedEntries--;
      } else {
	 fnode->fn_Marked     = 1;
	 freq->fr_MarkedSize += fnode->fn_Size;
	 freq->fr_MarkedEntries++;
      }
      print_freq_lines(freq, (struct MinNode *)fnode, (USHORT)
					    freq->fr_CursorLine, (USHORT)1);
      move_freq_cursor_down(freq);
   }
}
	/* Unmark all selected entries in active file requester */

   VOID
action_unmark_all_files(VOID)
{
   struct FileRequest  *freq  = &file_req[active_freq];
   struct FileNode     *fnode = (struct FileNode *)
					  freq->fr_Display.d_List->mlh_Head;
   ULONG i, num_entries = freq->fr_Display.d_NumEntries;

   if ((freq->fr_Mode == FREQ_MODE_NORMAL || freq->fr_Mode ==
			     FREQ_MODE_FIND) && freq->fr_CursorLine != -1) {
      hcomp_freq_cursor(freq);
      print_info_line(INFO_LINE_MODE_EMPTY);
      for (i = 0; i < num_entries; i++) {
	 fnode->fn_Marked = 0;   /* unmark entry */
	 fnode            = (struct FileNode *)fnode->fn_Node.mln_Succ;
      }
      freq->fr_MarkedEntries = 0;
      freq->fr_MarkedSize    = 0;
      print_freq_lines(freq, freq->fr_Display.d_FirstVisibleNode, (USHORT)
					0, freq->fr_Display.d_VisibleLines);
      hcomp_freq_cursor(freq);
      print_info_line(INFO_LINE_MODE_NORMAL);
   }
}
	/* Run file or enter directory from cursor line */

   VOID
action_user_function(USHORT num)
{
   struct CommandLineInterface *cli = BTOC(_parent_proc->pr_CLI);
   struct FileRequest  *freq  = &file_req[active_freq];
   struct FileNode     *fnode = NULL;
   BYTE  *ptr, *args, *func = user_function[num], *prog = &path1_buffer[0];
   BPTR  cd_lock;
   SHORT error = VSH_STATUS_NORMAL;

   if (cli == save_cli && *func != '\0') {
      if (freq->fr_Mode == FREQ_MODE_NORMAL || freq->fr_Mode ==
							   FREQ_MODE_FIND) {
	 fnode = get_file_node_under_cursor(freq);
      }
      if (fnode && *func == '[' && *(func + 1) == ']') {
	 if (!(ptr = append_path_name(prog, freq, fnode,
						     APPEND_MODE_NORMAL))) {
	    error = VSH_ERROR_LOCK_FAILED;
	 } else {
	    strcpy(ptr, func + 2);
	    if (!(args = (BYTE *)strchr(ptr, ' '))) {   /* no arguments ? */
	       args = empty;
	    } else {
	       *args++ = '\0';
	    }
	 }
      } else {
	 strcpy(prog, func);
	 if (*prog == '"') {   /* quoted file name ? */
	    if (!(args = (BYTE *)strchr(++prog, '"'))) {
	       error = VSH_ERROR_MISSING_SECOND_QUOTE;
	    } else {
	       if (prog == args) {   /* quoted string empty ? */
		  error = VSH_ERROR_NO_FILENAME;
	       } else {
		  *args++ = '\0';   /* mark end of file name */
		  if (*args == '\0') {   /* no arguments ? */
		     args = empty;
		  }
	       }
	    }
	 } else {
	    if (!(args = (BYTE *)strchr(prog, ' '))) {   /* no arguments ? */
	       args = empty;
	    } else {
	       *args++ = '\0';
	    }
	 }
      }
      if (error == VSH_STATUS_NORMAL) {
	 if (fnode && (ptr = strchr(args, '[')) && *(ptr + 1) == ']') {
	    if (!(ptr = append_path_name(ptr, freq, fnode,
						     APPEND_MODE_QUOTED))) {
	       error = VSH_ERROR_LOCK_FAILED;
	    } else {
	       strcpy(ptr, strchr(func, ']') + 1);
	    }
	 }
	 if (error == VSH_STATUS_NORMAL) {
	    print_status(VSH_STATUS_EXECUTE_USER_FUNCTION);   /* execute user function */
	    action_display_mode();
	    print_fkey_text(FKEY_MODE_NONE);
	    cd_lock = (BPTR)CurrentDir(freq->fr_DirLock);
	    error   = execute(prog, args);
	    CurrentDir(cd_lock);
	    change_fkey_text();
	 }
      }
      print_status(error);
   }
}
	/* Change user function */

   VOID
action_change_user_function(USHORT num)
{
   BYTE   *ptr, *func_text;
   USHORT len;
   SHORT  error = VSH_STATUS_NORMAL;

   if (func_text = get_input(INPUT_MODE_USER_FUNCTION, user_function[num])) {

      /* New fkey name ? */
      if (ptr = strchr(func_text, (USHORT)';')) {

	 /* Strip fkey name from user func */
	 *ptr++ = (BYTE)'\0';
	 if (len = strlen(ptr)) {
	    strcpy(user_fkey_text[num], "      ");
	    strncpy(user_fkey_text[num], ptr, (size_t)
		       (len > MAX_FKEY_NAME_LEN ? MAX_FKEY_NAME_LEN : len));
	 }
      }

      /* Strip white space */
      ptr = func_text;
      while (*ptr == ' ' || *ptr == '\t') {
	 ptr++;
      }

      /* New user func ? */
      if (*ptr != '\0') {
	 strcpy(user_function[num], ptr);
      }
      change_fkey_text();
   }
   print_status(error);
}
	/* Select entries to mark or unmark by pattern */

   VOID
action_pattern_select(USHORT mode)
{
   struct FileRequest  *freq  = &file_req[active_freq];
   struct FileNode     *fnode = (struct FileNode *)
					  freq->fr_Display.d_List->mlh_Head;
   ULONG  i, num_entries = freq->fr_Display.d_NumEntries;
   BYTE   *default_input, *pattern_text, *pattern = &path1_buffer[0],
	  *file = &file1_buffer[0];
   USHORT input_mode;
   SHORT  error = VSH_STATUS_NORMAL;

   if ((freq->fr_Mode == FREQ_MODE_NORMAL || freq->fr_Mode ==
			     FREQ_MODE_FIND) && freq->fr_CursorLine != -1) {

      /* Calc input mode and default input text */
      if (mode == PATTERN_SELECT_MODE_MARK) {
	 input_mode    = INPUT_MODE_SELECT_PATTERN_MARK;
	 default_input = &freq->fr_MarkPattern[0];
      } else {
	 input_mode    = INPUT_MODE_SELECT_PATTERN_UNMARK;
	 default_input = &freq->fr_UnmarkPattern[0];
      }

      /* Get pattern text and convert it to a valid pattern */
      if (pattern_text = get_input(input_mode, default_input)) {
	 if (strlen(pattern_text) > MAX_PATTERN_LEN ||
				 PreParse(pattern_text, pattern) == FALSE) {
	    error = VSH_ERROR_INVALID_PATTERN;
	 } else {
	    hcomp_freq_cursor(freq);
	    print_info_line(INFO_LINE_MODE_EMPTY);
	    strcpy(default_input, pattern_text);   /* save new pattern */

	    /* Compare all entries with selected pattern */
	    for (i = 0; i < num_entries; i++) {
	       strncpy(file, &fnode->fn_Text[0], (size_t)fnode->fn_NameLen);
	       *(file + fnode->fn_NameLen) = '\0';
	       if (PatternMatch(pattern, file) == TRUE) {
		  if (mode == PATTERN_SELECT_MODE_MARK) {
		     if (!fnode->fn_Marked) {

			/* Mark entry */
			fnode->fn_Marked     = 1;
			freq->fr_MarkedSize += fnode->fn_Size;
			freq->fr_MarkedEntries++;
		     }
		  } else {
		     if (fnode->fn_Marked) {

			/* Unmark entry */
			fnode->fn_Marked     = 0;
			freq->fr_MarkedSize -= fnode->fn_Size;
			freq->fr_MarkedEntries--;
		     }
		  }
	       }
	       fnode = (struct FileNode *)fnode->fn_Node.mln_Succ;
	    }

	    /* Refresh file requester and info line */
	    print_freq_lines(freq, freq->fr_Display.d_FirstVisibleNode,
				(USHORT)0, freq->fr_Display.d_VisibleLines);
	    hcomp_freq_cursor(freq);
	    print_info_line(INFO_LINE_MODE_NORMAL);
	    change_fkey_text();
	 }
      }
   }
   print_status(error);
}
	/* Compare directories listed in both file requesters */

   VOID
action_compare_directories(VOID)
{
   struct FileRequest  *freq1 = &file_req[active_freq],
		       *freq2 = &file_req[(active_freq ? 0 : 1)];
   struct MinList      *flist1 = freq1->fr_Display.d_List,
		       *flist2 = freq2->fr_Display.d_List;
   struct FileNode     *fnode1, *fnode2;
   struct DateStamp    *date1, *date2;
   ULONG i, num_entries = freq1->fr_Display.d_NumEntries;
   BOOL  mark_flag;
   SHORT error = VSH_STATUS_NORMAL;

   if (freq1->fr_CursorLine != -1) {
      if (freq1->fr_Mode != freq2->fr_Mode) {
	 error = VSH_ERROR_DIFFERENT_DIRECTORY_MODES;
      } else {
	 print_status(VSH_STATUS_COMPARING_DIRECTORIES);
	 hcomp_freq_cursor(freq1);
	 print_info_line(INFO_LINE_MODE_EMPTY);
	 print_fkey_text(FKEY_MODE_NONE);
	 /* file node loop */
	 fnode1 = (struct FileNode *)freq1->fr_Display.d_List->mlh_Head;
	 for (i = 0; i < num_entries; i++) {
	    if (!(fnode2 = search_file_node((struct FileNode *)
		    freq2->fr_Display.d_List->mlh_Head, &fnode1->fn_Text[0],
						     fnode1->fn_NameLen))) {
	       mark_flag = TRUE;
	    } else {
	       /* compare file node data */
	       date1 = &fnode1->fn_Date;
	       date2 = &fnode2->fn_Date;
	       if (fnode1->fn_Size == fnode2->fn_Size &&
			   fnode1->fn_Protection == fnode2->fn_Protection &&
					 date1->ds_Days == date2->ds_Days &&
				     date1->ds_Minute == date2->ds_Minute &&
					 date1->ds_Tick == date2->ds_Tick) {
		  mark_flag = FALSE;
	       } else {
		  mark_flag = TRUE;
	       }
	    }
	    if (mark_flag == TRUE && !fnode1->fn_Marked) {
	       /* mark file node */
	       fnode1->fn_Marked     = 1;
	       freq1->fr_MarkedSize += fnode1->fn_Size;
	       freq1->fr_MarkedEntries++;
	    }
	    fnode1 = (struct FileNode *)fnode1->fn_Node.mln_Succ;
	 }
	 print_freq_lines(freq1, freq1->fr_Display.d_FirstVisibleNode,
			       (USHORT)0, freq1->fr_Display.d_VisibleLines);
	 hcomp_freq_cursor(freq1);
	 print_info_line(INFO_LINE_MODE_NORMAL);
	 change_fkey_text();
      }
      print_status(error);
   }
}
