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

	/* Includes */

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

	/* Show configuration for VSh */

   VOID
action_config(VOID)
{
   struct Gadget       *gadget_buffer, *gad;
   struct StringInfo   *sinfo_buffer, *info;
   struct IntuiText    *itext_buffer, *text;
   struct ConfigEntry  *ce;
   BYTE   *string_buffer, *buffer;
   BOOL   success = FALSE;
   USHORT i, text_len, max_text_len = 0, width, max_width = 0, left_offset,
	  top_offset = BORDER_TOP + MAX_OUTPUT_HEIGHT / 2 -
					       (MAX_CONFIG_ENTRIES * 9) / 2;
   event_mode = EVENT_MODE_IGNORE;
   if (gadget_buffer = (struct Gadget *)AllocMem((LONG)(MAX_CONFIG_ENTRIES *
			sizeof(struct Gadget)), MEMF_PUBLIC | MEMF_CLEAR)) {
      if (sinfo_buffer = (struct StringInfo *)AllocMem((LONG)
			   (MAX_CONFIG_ENTRIES * sizeof(struct StringInfo)),
						MEMF_PUBLIC | MEMF_CLEAR)) {
	 if (string_buffer = AllocMem((LONG)(MAX_CONFIG_ENTRIES *
		   (MAX_CONFIG_ENTRY_LEN + 1)), MEMF_PUBLIC | MEMF_CLEAR)) {
	    if (itext_buffer = (struct IntuiText *)AllocMem((LONG)
			    (MAX_CONFIG_ENTRIES * sizeof(struct IntuiText)),
						MEMF_PUBLIC | MEMF_CLEAR)) {
	       /* Initialize string gadgets */
	       ce     = &config_entry[i];
	       gad    = gadget_buffer;
	       info   = sinfo_buffer;
	       text   = itext_buffer;
	       buffer = string_buffer;
	       for (i = 0; i < MAX_CONFIG_ENTRIES; i++) {
		  if ((text_len = strlen(ce->ce_Text) + 1) > max_text_len) {
		     max_text_len = text_len;
		  }
		  if ((width = (ce->ce_MaxStringLen + 1) * 8) > max_width) {
		     max_width = width;
		  }
		  text->FrontPen   = COLOR1;
		  text->BackPen    = COLOR2;
		  text->DrawMode   = JAM1;
		  text->LeftEdge   = -(text_len * 8);
		  text->ITextFont  = &topaz80;
		  text->IText      = (UBYTE *)ce->ce_Text;

		  info->Buffer     = (UBYTE *)buffer;
		  info->MaxChars   = ce->ce_MaxStringLen + 1;

		  gad->TopEdge     = top_offset + i * 9;
		  gad->Width       = width;
		  gad->Height      = 8;
		  gad->Flags       = GADGHCOMP;
		  gad->GadgetType  = STRGADGET;
		  gad->Activation  = ce->ce_Activation;
		  gad->GadgetText  = text;
		  gad->SpecialInfo = (APTR)info;
		  gad->GadgetID    = i;
		  if (i < (MAX_CONFIG_ENTRIES - 1)) {
		     gad->NextGadget = gad + 1;
		  } else {
		     gad->NextGadget = NULL;
		  }
		  ce++;
		  gad++;
		  info++;
		  text++;
		  buffer += MAX_CONFIG_ENTRY_LEN + 1;
	       }
	       if ((max_text_len + max_width / 8) > (max_line_len - 2)) {
		  left_offset = BORDER_LEFT + (max_text_len + 1) * 8;
		  max_width   = ((max_line_len - 2) - max_text_len) * 8;
	       } else {
		  left_offset = (vsh_width - (max_text_len * 8 + max_width))
						     / 2 + max_text_len * 8;
	       }

	       /* Set left edge and width of gadgets */
	       gad = gadget_buffer;
	       for (i = 0; i < MAX_CONFIG_ENTRIES; i++, gad++) {
		  gad->LeftEdge = left_offset;
		  if (gad->Width > max_width) {
		     gad->Width = max_width;
		  }
	       }
	       fill_config_gadget_buffers(gadget_buffer);
	       perform_config_action(gadget_buffer);
	       success = TRUE;
	       FreeMem(itext_buffer, (LONG)(MAX_CONFIG_ENTRIES *
						 sizeof(struct IntuiText)));
	    }
	    FreeMem(string_buffer, (LONG)(MAX_CONFIG_ENTRIES *
					       (MAX_CONFIG_ENTRY_LEN + 1)));
	 }
	 FreeMem(sinfo_buffer, (LONG)(MAX_CONFIG_ENTRIES *
						sizeof(struct StringInfo)));
      }
      FreeMem(gadget_buffer, (LONG)(MAX_CONFIG_ENTRIES *
						    sizeof(struct Gadget)));
   }
   if (success == FALSE) {
      print_status(VSH_ERROR_OUT_OF_MEM);
   } else {
      draw_display(FULL_DISPLAY);
   }
   event_mode = EVENT_MODE_NORMAL;
}
	/* Perform configuration action */

   VOID
perform_config_action(struct Gadget *gadget_list)
{
   struct Gadget  *error_gadget, *active_gadget = gadget_list;
   BOOL keepon = TRUE;

   event_mode = EVENT_MODE_CONFIG;
   qualifier  = QUALIFIER_NONE;
   if (! show_flag) {  /* hidden display ? */
      clear_display(PART_DISPLAY);
   } else {
      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));
   }
   SetAPen(con_rport, (LONG)COLOR2);
   RectFill(con_rport, (LONG)BORDER_LEFT, (LONG)BORDER_TOP, (LONG)(vsh_width
				 - BORDER_RIGHT - 1), (LONG)(cli_vpos - 4));
   display_text(COLOR3, COLOR2, (USHORT)((vsh_width - 13 * 8) / 2), (USHORT)
					 (BORDER_TOP + 8), "Configuration");
   SetFont(&con_window->WScreen->RastPort, con_font);   /* need console 8x8 text font for string gadgets */
   RefreshGadgets(gadget_list, con_window, NULL);
   display_text(COLOR3, COLOR2, (USHORT)((vsh_width - 64 * 8) / 2), (USHORT)
						     (cli_vpos - 3 - 2 * 8),
	"Use arrow keys, RETURN or SHIFT RETURN to change configuration !");
   print_fkey_text(FKEY_MODE_CONFIG);
   do {
      ULONG signals;

      AddGList(con_window, gadget_list, -1L, -1L, NULL);
      ActivateGadget(active_gadget, con_window, NULL);
      signals = Wait(SIGF_ACTION);
      RemoveGList(con_window, gadget_list, -1L);
      switch (action) {
	 case VSH_ACTION_F1 :   /* load */
	    if (read_config_file() == FALSE) {
	       DisplayBeep(NULL);
	       set_default_config();
	    }
	    prepare_con_window();
	    keepon = FALSE;
	    break;
	 case VSH_ACTION_F2 :   /* save */
	    if (!(active_gadget = check_config(gadget_list))) {
	       set_new_config(gadget_list);
	       if (write_config_file() == FALSE) {
		  DisplayBeep(NULL);
	       }
	       prepare_con_window();
	       keepon = FALSE;
	    }
	    break;
	 case VSH_ACTION_F3 :   /* defaults */
	    set_default_config();
	    prepare_con_window();
	    keepon = FALSE;
	    break;
	 case VSH_ACTION_F4 :   /* use */
	    if (!(active_gadget = check_config(gadget_list))) {
	       set_new_config(gadget_list);
	       prepare_con_window();
	       keepon = FALSE;
	    }
	    break;
	 case VSH_ACTION_SHIFT_GADGET_END_KEY :   /* up */
	    if (error_gadget = check_config(gadget_list)) {
	       active_gadget = error_gadget;
	    } else {
	       if (active_gadget->GadgetID) {
		  active_gadget--;
	       } else {
		  active_gadget = gadget_list + (MAX_CONFIG_ENTRIES - 1);
	       }
	    }
	    break;
	 case VSH_ACTION_GADGET_END_KEY :   /* down */
	    if (error_gadget = check_config(gadget_list)) {
	       active_gadget = error_gadget;
	    } else {
	       if (active_gadget->GadgetID < (MAX_CONFIG_ENTRIES - 1)) {
		  active_gadget++;
	       } else {
		  active_gadget = gadget_list;
	       }
	    }
	    break;
	 case VSH_ACTION_QUIT :   /* cancel */
	 case VSH_ACTION_ESC :
	    keepon = FALSE;
	    break;
      }
   } while (keepon == TRUE);
   SetFont(&con_window->WScreen->RastPort, old_wb_font);   /* restore original font */
   event_mode = EVENT_MODE_IGNORE;
   action     = VSH_ACTION_NONE;
}
	/* Fill configuration string gadget buffers */

   VOID
fill_config_gadget_buffers(struct Gadget *gad)
{
   struct StringInfo  *sinfo;
   BYTE   *buffer;
   USHORT i;

   for (i = 0; i < MAX_CONFIG_ENTRIES; i++) {
      sinfo  = (struct StringInfo *)gad++->SpecialInfo;
      buffer = (BYTE *)sinfo->Buffer;
      switch (i) {
	 case CONFIG_ENTRY_LEFT_EDGE :
	    SPrintf(buffer, "%d", con_window->LeftEdge);
	    sinfo->LongInt = con_window->LeftEdge;
	    break;
	 case CONFIG_ENTRY_TOP_EDGE :
	    SPrintf(buffer, "%d", con_window->TopEdge);
	    sinfo->LongInt = con_window->TopEdge;
	    break;
	 case CONFIG_ENTRY_WIDTH :
	    SPrintf(buffer, "%d", vsh_width);
	    sinfo->LongInt = vsh_width;
	    break;
	 case CONFIG_ENTRY_HEIGHT :
	    SPrintf(buffer, "%d", vsh_height);
	    sinfo->LongInt = vsh_height;
	    break;
	 case CONFIG_ENTRY_CLI_LINES :
	    SPrintf(buffer, "%d", vsh_cli_lines);
	    sinfo->LongInt = vsh_cli_lines;
	    break;
	 case CONFIG_ENTRY_SCROLL_SPEED :
	    SPrintf(buffer, "%d", vsh_scroll_speed);
	    sinfo->LongInt = vsh_scroll_speed;
	    break;
	 case CONFIG_ENTRY_KEYBOARD_TYPE :
	    SPrintf(buffer, "%d", vsh_keyboard_type);
	    sinfo->LongInt = vsh_keyboard_type;
	    break;
	 case CONFIG_ENTRY_DUMP_MODE :
	    SPrintf(buffer, "%d", vsh_dump_mode);
	    sinfo->LongInt = vsh_dump_mode;
	    break;
	 case CONFIG_ENTRY_EDITOR_NAME :
	    strcpy(buffer, vsh_editor_name);
	    break;
	 case CONFIG_ENTRY_EDITOR_OPTS :
	    strcpy(buffer, vsh_editor_opts);
	    break;
      }
      sinfo->BufferPos = strlen(buffer);
   }
}
	/* Check configuration for validity */

   struct Gadget *
check_config(struct Gadget *gadget_list)
{
   struct Gadget       *gad = gadget_list, *error_gadget = NULL;
   struct ConfigEntry  *ce = &config_entry[0];
   struct StringInfo   *sinfo;
   LONG   value;
   USHORT i, new_vsh_left, new_vsh_top, new_vsh_width, new_vsh_height,
	  new_vsh_cli_lines;
   BYTE   *buffer;

   for (i = 0; i < MAX_CONFIG_ENTRIES && !error_gadget; i++, gad++, ce++) {
      sinfo  = (struct StringInfo *)gad->SpecialInfo;
      value  = sinfo->LongInt;
      buffer = (BYTE *)sinfo->Buffer;
      if (ce->ce_Activation == LONGINT && (value < ce->ce_MinValue ||
						 value > ce->ce_MaxValue)) {
	 error_gadget = gad;
      } else {
	 switch (i) {
	    case CONFIG_ENTRY_LEFT_EDGE :
	       new_vsh_left = value;
	       break;
	    case CONFIG_ENTRY_TOP_EDGE :
	       new_vsh_top = value;
	       break;
	    case CONFIG_ENTRY_WIDTH :
	       new_vsh_width = value;
	       break;
	    case CONFIG_ENTRY_HEIGHT :
	       new_vsh_height = value;
	       break;
	    case CONFIG_ENTRY_CLI_LINES :
	       new_vsh_cli_lines = value;
	       break;
	    case CONFIG_ENTRY_EDITOR_NAME :
	       if (*buffer == '\0') {
		  error_gadget = gad;
	       }
	       break;
	 }
      }
   }
   if (!error_gadget) {   /* check con window dimension */
      if ((new_vsh_left + new_vsh_width) > wb_width) {
	 error_gadget = gadget_list + CONFIG_ENTRY_LEFT_EDGE;
      } else {
	 if ((new_vsh_top + new_vsh_height) > wb_height) {
	    error_gadget = gadget_list + CONFIG_ENTRY_TOP_EDGE;
	 } else {
	    if (new_vsh_cli_lines > DEFAULT_CLI_LINES && (MIN_VSH_HEIGHT +
				(new_vsh_cli_lines - DEFAULT_CLI_LINES) * 8)
							 > new_vsh_height) {
	       error_gadget = gadget_list + CONFIG_ENTRY_CLI_LINES;
	    }
	 }
      }
   }
   if (error_gadget) {
      DisplayBeep(NULL);
   }
   return(error_gadget);
}
	/* Set default values for VSh configuration */

   VOID
set_default_config(VOID)
{
   USHORT i;

   /* Set default console window dimension */
   vsh_left          = DEFAULT_LEFT_EDGE;
   vsh_top           = DEFAULT_TOP_EDGE;
   vsh_width         = wb_width;
   vsh_height        = wb_height;
   vsh_cli_lines     = DEFAULT_CLI_LINES;
   vsh_scroll_speed  = DEFAULT_SCROLL_SPEED;
   vsh_keyboard_type = DEFAULT_KEYBOARD_TYPE;
   vsh_dump_mode     = DEFAULT_DUMP_MODE;
   strcpy(vsh_editor_name, DEFAULT_EDITOR_NAME);
   strcpy(vsh_editor_opts, DEFAULT_EDITOR_OPTS);

   /* Init user func fkey texts and user funcs */
   for (i = 0; i < MAX_FKEYS; i++) {
      SPrintf(user_fkey_text[i], "User%-2d", i + 1);
      *user_function[i] = '\0';
   }
}
	/* Set new values for VSh configuration */

   VOID
set_new_config(struct Gadget *gad)
{
   struct StringInfo  *sinfo;
   BYTE   *buffer;
   USHORT i;

   for (i = 0; i < MAX_CONFIG_ENTRIES; i++) {
      sinfo  = (struct StringInfo *)gad++->SpecialInfo;
      buffer = (BYTE *)sinfo->Buffer;
      switch (i) {
	 case CONFIG_ENTRY_LEFT_EDGE :
	    vsh_left = sinfo->LongInt;
	    break;
	 case CONFIG_ENTRY_TOP_EDGE :
	    vsh_top = sinfo->LongInt;
	    break;
	 case CONFIG_ENTRY_WIDTH :
	    vsh_width = sinfo->LongInt;
	    break;
	 case CONFIG_ENTRY_HEIGHT :
	    vsh_height = sinfo->LongInt;
	    break;
	 case CONFIG_ENTRY_CLI_LINES :
	    vsh_cli_lines = sinfo->LongInt;
	    break;
	 case CONFIG_ENTRY_SCROLL_SPEED :
	    vsh_scroll_speed = sinfo->LongInt;
	    break;
	 case CONFIG_ENTRY_KEYBOARD_TYPE :
	    vsh_keyboard_type = sinfo->LongInt;
	    break;
	 case CONFIG_ENTRY_DUMP_MODE :
	    vsh_dump_mode = sinfo->LongInt;
	    break;
	 case CONFIG_ENTRY_EDITOR_NAME :
	    strcpy(vsh_editor_name, buffer);
	    break;
	 case CONFIG_ENTRY_EDITOR_OPTS :
	    strcpy(vsh_editor_opts, buffer);
	    break;
      }
   }
}
	/* Read config file and get informations out of it */

   BOOL
read_config_file(VOID)
{
   BPTR   fh;
   BYTE   *buffer = &path1_buffer[0];
   USHORT i;
   BOOL   success = FALSE;

   if (fh = (BPTR)Open(vsh_config_file, (LONG)MODE_OLDFILE)) {
      if ((success = read_config_data(fh, buffer, (LONG)
				  (strlen(vsh_config_file) + 1))) == TRUE) {
	 if (strcmp(buffer, vsh_config_file)) {
	    success = FALSE;
	 } else {
	    for (i = 0; i < MAX_CONFIG_ENTRIES && success == TRUE; i++) {
	       switch (i) {
		  case CONFIG_ENTRY_LEFT_EDGE :
		     success = read_config_data(fh, (BYTE *)&vsh_left,
						    (LONG)sizeof(vsh_left));
		     break;
		  case CONFIG_ENTRY_TOP_EDGE :
		     success = read_config_data(fh, (BYTE *)&vsh_top, (LONG)
							   sizeof(vsh_top));
		     break;
		  case CONFIG_ENTRY_WIDTH :
		     success = read_config_data(fh, (BYTE *)&vsh_width,
						   (LONG)sizeof(vsh_width));
		     break;
		  case CONFIG_ENTRY_HEIGHT :
		     success = read_config_data(fh, (BYTE *)&vsh_height,
						  (LONG)sizeof(vsh_height));
		     break;
		  case CONFIG_ENTRY_CLI_LINES :
		     success = read_config_data(fh, (BYTE *)&vsh_cli_lines,
					       (LONG)sizeof(vsh_cli_lines));
		     break;
		  case CONFIG_ENTRY_SCROLL_SPEED :
		     success = read_config_data(fh, (BYTE *)
			 &vsh_scroll_speed, (LONG)sizeof(vsh_scroll_speed));
		     break;
		  case CONFIG_ENTRY_KEYBOARD_TYPE :
		     success = read_config_data(fh, (BYTE *)
		       &vsh_keyboard_type, (LONG)sizeof(vsh_keyboard_type));
		     break;
		  case CONFIG_ENTRY_DUMP_MODE :
		     success = read_config_data(fh, (BYTE *)
			       &vsh_dump_mode, (LONG)sizeof(vsh_dump_mode));
		     break;
		  case CONFIG_ENTRY_EDITOR_NAME :
		     success = read_config_data(fh, vsh_editor_name, (LONG)
						 (MAX_EDITOR_NAME_LEN + 1));
		     break;
		  case CONFIG_ENTRY_EDITOR_OPTS :
		     success = read_config_data(fh, vsh_editor_opts, (LONG)
						 (MAX_EDITOR_OPTS_LEN + 1));
		     break;
	       }
	    }

	    /* Read user functions */
	    for (i = 0; i < MAX_USER_FUNCTIONS && success == TRUE; i++) {
	       if ((success = read_config_data(fh, user_fkey_text[i], (LONG)
					(MAX_FKEY_NAME_LEN + 1))) == TRUE) {
		  success = read_config_data(fh, user_function[i], (LONG)
					       (MAX_USER_FUNCTION_LEN + 1));
	       }
	    }
	 }
      }
      Close(fh);
   }
   if (success == TRUE) {

      /* Check console window dimension */
      if ((vsh_left + vsh_width) > wb_width || (vsh_top + vsh_height) >
								wb_height) {
	 /* Set default console window dimension */
	 vsh_left   = DEFAULT_LEFT_EDGE;
	 vsh_top    = DEFAULT_TOP_EDGE;
	 vsh_width  = wb_width;
	 vsh_height = wb_height;
	 if (vsh_cli_lines > DEFAULT_CLI_LINES && (MIN_VSH_HEIGHT +
		    (vsh_cli_lines - DEFAULT_CLI_LINES) * 8) > vsh_height) {
	    vsh_cli_lines = DEFAULT_CLI_LINES + (vsh_height -
							MIN_VSH_HEIGHT) / 8;
	 }
      }
   }
   return(success);
}
	/* Read data from config file */

   BOOL
read_config_data(BPTR fh, BYTE *buffer, ULONG size)
{
   BOOL success = TRUE;

   if (Read(fh, buffer, size) != size) {
      success = FALSE;
   }
   return(success);
}
	/* Write config file */

   BOOL
write_config_file(VOID)
{
   BPTR   fh;
   USHORT i;
   BOOL   success = FALSE;

   if (fh = (BPTR)Open(vsh_config_file, (LONG)MODE_NEWFILE)) {
      if ((success = write_config_data(fh, vsh_config_file, (LONG)
				  (strlen(vsh_config_file) + 1))) == TRUE) {
	 for (i = 0; i < MAX_CONFIG_ENTRIES && success == TRUE; i++) {
	    switch (i) {
	       case CONFIG_ENTRY_LEFT_EDGE :
		  success = write_config_data(fh, (BYTE *)&vsh_left, (LONG)
							  sizeof(vsh_left));
		  break;
	       case CONFIG_ENTRY_TOP_EDGE :
		  success = write_config_data(fh, (BYTE *)&vsh_top, (LONG)
							   sizeof(vsh_top));
		  break;
	       case CONFIG_ENTRY_WIDTH :
		  success = write_config_data(fh, (BYTE *)&vsh_width, (LONG)
							 sizeof(vsh_width));
		  break;
	       case CONFIG_ENTRY_HEIGHT :
		  success = write_config_data(fh, (BYTE *)&vsh_height,
						  (LONG)sizeof(vsh_height));
		  break;
	       case CONFIG_ENTRY_CLI_LINES :
		  success = write_config_data(fh, (BYTE *)&vsh_cli_lines,
					       (LONG)sizeof(vsh_cli_lines));
		  break;
	       case CONFIG_ENTRY_SCROLL_SPEED :
		  success = write_config_data(fh, (BYTE *)&vsh_scroll_speed,
					    (LONG)sizeof(vsh_scroll_speed));
		  break;
	       case CONFIG_ENTRY_KEYBOARD_TYPE :
		  success = write_config_data(fh, (BYTE *)
		       &vsh_keyboard_type, (LONG)sizeof(vsh_keyboard_type));
		  break;
	       case CONFIG_ENTRY_DUMP_MODE :
		  success = write_config_data(fh, (BYTE *)
			       &vsh_dump_mode, (LONG)sizeof(vsh_dump_mode));
		  break;
	       case CONFIG_ENTRY_EDITOR_NAME :
		  success = write_config_data(fh, vsh_editor_name, (LONG)
						 (MAX_EDITOR_NAME_LEN + 1));
		  break;
	       case CONFIG_ENTRY_EDITOR_OPTS :
		  success = write_config_data(fh, vsh_editor_opts, (LONG)
						 (MAX_EDITOR_OPTS_LEN + 1));
		  break;
	    }
	 }

	 /* Write user functions */
	 for (i = 0; i < MAX_USER_FUNCTIONS && success == TRUE; i++) {
	    if ((success = write_config_data(fh, user_fkey_text[i], (LONG)
					(MAX_FKEY_NAME_LEN + 1))) == TRUE) {
	       success = write_config_data(fh, user_function[i], (LONG)
					       (MAX_USER_FUNCTION_LEN + 1));
	    }
	 }
      }
      Close(fh);
      if (success == FALSE) {

	 /* Delete invalid config file */
	 DeleteFile(vsh_config_file);
      }
   }
   return(success);
}
	/* Write data to config file */

   BOOL
write_config_data(BPTR fh, BYTE *buffer, ULONG size)
{
   BOOL success = TRUE;

   if (Write(fh, buffer, size) != size) {
      success = FALSE;
   }
   return(success);
}
