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

	/* Includes */

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

	/* Structures */

struct StartupMsg {
	struct Message  sm_Message;
	struct Process  *sm_CLIProcess;
	struct Window   *sm_ConWindow;
	struct Device   *sm_ConDevice;
	struct ConUnit  *sm_ConUnit;
	BYTE	*sm_LeftPath;	/* path for left file requester */
	BYTE	*sm_RightPath;	/* path for right file requester */
	USHORT	sm_Flags;	/* used for HIDE flag */
};
	/* Main - waits for startup msg and installs input event handler */

   VOID
_main(VOID)
{
   struct MsgPort     *mp;
   struct StartupMsg  *sm;
   BYTE *path;

   /* Wait for startup msg */
   main_task = FindTask(NULL);
   mp        = &((struct Process *)main_task)->pr_MsgPort;
   WaitPort(mp);
   if (sm = (struct StartupMsg *)GetMsg(mp)) {

      /* Get data from startup msg and return it */
      _parent_proc       = sm->sm_CLIProcess;
      save_cli           = BTOC(_parent_proc->pr_CLI);
      con_input_fhandle  = BTOC(_parent_proc->pr_CIS);
      con_output_fhandle = BTOC(_parent_proc->pr_COS);
      con_window         = sm->sm_ConWindow;
      con_rport          = con_window->RPort;
      con_device         = sm->sm_ConDevice;
      con_unit           = sm->sm_ConUnit;
      show_flag          = (sm->sm_Flags == 1 ? 0 : 1);

      /* Copy given path names to allocated buffer */
      if (!(path = sm->sm_LeftPath)) {
	 dir_arg[0] = NULL;
      } else {
	 if (dir_arg[0] = AllocMem((LONG)(strlen(path) + 1), (LONG)
							     MEMF_PUBLIC)) {
	    strcpy(dir_arg[0], path);
	 }
      }
      if (!(path = sm->sm_RightPath)) {
	 dir_arg[1] = NULL;
      } else {
	 if (dir_arg[1] = AllocMem((LONG)(strlen(path) + 1), (LONG)
							     MEMF_PUBLIC)) {
	    strcpy(dir_arg[1], path);
	 }
      }

      /* Send startup message back to VSh */
      ReplyMsg(&sm->sm_Message);

      /* Alloc respources */
      if (ArpBase = OpenLibrary(ArpName, ArpVersion)) {

	 /* Use libraries arp.library has already opened for us */
	 GfxBase       = (struct GfxBase *)ArpBase->GfxBase;
	 IntuitionBase = (struct IntuitionBase *)ArpBase->IntuiBase;

	 /* Check if started from WShell */
	 SPrintf(&line1_buffer[0], "WSH_%ld", _parent_proc->pr_TaskNum);
	 wshell_flag = (FindPort(&line1_buffer[0]) ? 1 : 0);

	 /* Build process name */
	 SPrintf(&process_name[0], PROCESS_NAME, _parent_proc->pr_TaskNum);

	 /* Install input event handler */
	 if (vsh_port = CreatePort(&process_name[0], 0L)) {
	    if (input_req = CreateStdIO(vsh_port)) {
	       if (!OpenDevice("input.device", 0L, (struct IORequest *)
							   input_req, 0L)) {
		  /* Init interrupt struct */
		  interrupt.is_Node.ln_Name = &process_name[0];
		  interrupt.is_Node.ln_Pri  = 51;   /* above Intuition */
		  interrupt.is_Code         = (VOID (*)())
						       &input_event_handler;
#asm
	move.l	a4,_interrupt+14	; use our data segment ptr as data for interrupt
#endasm
		  /* Init IOStdReq */
		  input_req->io_Command     = IND_ADDHANDLER;
		  input_req->io_Data        = (APTR)&interrupt;
		  input_req->io_Length      = sizeof(struct Interrupt);
		  if (DoIO((struct IORequest *)input_req)) {
		     Printf("Can't install input event handler !\n");
		  } else {
		     if (nil_handle = (BPTR)Open(nil, (LONG)MODE_NEWFILE)) {
			if (con_handle = (BPTR)Open(star, (LONG)
							    MODE_NEWFILE)) {
			   alloc_buffers();
			   Close(con_handle);
			}
			Close(nil_handle);
		     }
		     input_req->io_Command = IND_REMHANDLER;
		     DoIO((struct IORequest *)input_req);
		  }
		  CloseDevice((struct IORequest *)input_req);
	       }
	       DeleteStdIO(input_req);
	    }
	    DeletePort(vsh_port);
	 }
	 CloseLibrary(ArpBase);
      }

      /* Free path name buffer */
      if (path = dir_arg[0]) {
	 FreeMem(path, (LONG)(strlen(path) + 1));
      }
      if (path = dir_arg[1]) {
	 FreeMem(path, (LONG)(strlen(path) + 1));
      }
   }
}
	/* Allocate and initialize buffers */

   VOID
alloc_buffers(VOID)
{
   struct Screen    *wb_screen = con_window->WScreen;
   struct TextFont  *text_font;
   USHORT i;
   BYTE   *data_buffer, *ptr;

   /* Get current workbench dimension */
   wb_width    = wb_screen->Width;
   wb_height   = wb_screen->Height;
   wb_line_len = wb_width / 8;

   /* Need even line len for BltTemplate() -> EVEN source modulo!!! */
   if (wb_line_len & 1) {
      wb_line_len++;
   }

   /* Initialize max values in config entry array */
   config_entry[CONFIG_ENTRY_LEFT_EDGE].ce_MaxValue = wb_width -
							      MIN_VSH_WIDTH;
   config_entry[CONFIG_ENTRY_TOP_EDGE].ce_MaxValue  = wb_width -
							     MIN_VSH_HEIGHT;
   config_entry[CONFIG_ENTRY_WIDTH].ce_MaxValue     = wb_width;
   config_entry[CONFIG_ENTRY_HEIGHT].ce_MaxValue    = wb_height;
   config_entry[CONFIG_ENTRY_CLI_LINES].ce_MaxValue = (wb_height -
				    MIN_VSH_HEIGHT) / 8 + DEFAULT_CLI_LINES;
   if (data_buffer = AllocMem((LONG)((MAX_EDITOR_NAME_LEN + 1) +
	   (MAX_EDITOR_OPTS_LEN + 1) + MAX_FKEYS * ((MAX_USER_FUNCTION_LEN +
		     1) + (MAX_FKEY_LEN + 1))), MEMF_PUBLIC | MEMF_CLEAR)) {
      if (fib = (struct FileInfoBlock *)AllocMem((LONG)
		  sizeof(struct FileInfoBlock), MEMF_PUBLIC | MEMF_CLEAR)) {
	 if (idata = (struct InfoData *)AllocMem((LONG)
		       sizeof(struct InfoData), MEMF_PUBLIC | MEMF_CLEAR)) {
	    if (template_buffer = (UBYTE *)AllocMem((LONG)(wb_line_len * 8),
						 MEMF_PUBLIC | MEMF_CHIP)) {
	       if (font_data = (UBYTE *)AllocMem((LONG)(MAX_FONT_CHARS * 8),
							     MEMF_PUBLIC)) {
		  /* Clone console 8x8 font attr struct and open this font */
		  text_font              = con_rport->Font;
		  con_font_attr.ta_Name  = (STRPTR)
				      text_font->tf_Message.mn_Node.ln_Name;
		  con_font_attr.ta_YSize = text_font->tf_YSize;
		  con_font_attr.ta_Style = text_font->tf_Style;
		  con_font_attr.ta_Flags = text_font->tf_Flags;
		  if (con_font = OpenFont(&con_font_attr)) {
/*
Printf("font: name='%s'   XSize=%d   YSize=%d   Style=%d   Flags=%d\n",
   con_font->tf_Message.mn_Node.ln_Name, con_font->tf_XSize, con_font->tf_YSize, con_font->tf_Style, con_font->tf_Flags);
Printf("BaseLine=%d   Accessors=%d   Modulo=%d   LoChar=%d   HiChar=%d\n",
   con_font->tf_Baseline, con_font->tf_Accessors, con_font->tf_Modulo, con_font->tf_LoChar, con_font->tf_HiChar);
Printf("CharData=$%lx   CharLoc=$%lx   CharSpace=$%lx   CharKern=$%lx   Extension=$%lx\n",
   con_font->tf_CharData, con_font->tf_CharLoc, con_font->tf_CharSpace, con_font->tf_CharKern, con_font->tf_Message.mn_ReplyPort);
Delay(400L);
*/
		     /* Init font data */
		     unpack_font(con_font, font_data);
		     CopyMem((BYTE *)&special_chars[0][0],
						(BYTE *)font_data + 128 * 8,
					     (LONG)(MAX_SPECIAL_CHARS * 8));
		     /* Init string buffer ptrs */
		     vsh_editor_name = ptr  = data_buffer;
		     vsh_editor_opts = ptr += MAX_EDITOR_NAME_LEN + 1;

		     /* Init user func fkey text and buffer ptrs */
		     for (i = 0, ptr += MAX_EDITOR_OPTS_LEN + 1;
							 i < MAX_FKEYS; i++,
					 ptr += MAX_USER_FUNCTION_LEN + 1) {
			user_fkey_text[i] = ptr;
			user_function[i]  = ptr += MAX_FKEY_LEN + 1;
		     }

		     /* Save old window dimensions */
		     old_left        = con_window->LeftEdge;
		     old_top         = con_window->TopEdge;
		     old_width       = con_window->Width;
		     old_height      = con_window->Height;
		     old_min_width   = con_window->MinWidth,
		     old_min_height  = con_window->MinHeight,
		     old_max_width   = con_window->MaxWidth,
		     old_max_height  = con_window->MaxHeight,
		     old_flags       = con_window->Flags;
		     old_idcmp_flags = con_window->IDCMPFlags;
		     old_bleft       = con_window->BorderLeft;
		     old_btop        = con_window->BorderTop;
		     old_bright      = con_window->BorderRight;
		     old_bbottom     = con_window->BorderBottom;
		     old_wb_font     = wb_screen->RastPort.Font;

		     /* Turn on window border and refresh events (2nd used for Kick 2.0 simple refresh console windows !!!) */
		     con_window->Flags = old_flags & ~(BORDERLESS |
							     NOCAREREFRESH);
		     RefreshWindowFrame(con_window);
		     if (read_config_file() == FALSE) {
			set_default_config();
		     }
		     prepare_con_window();

		     /* Get refresh and timing events from intuition */
		     ModifyIDCMP(con_window, (ULONG)REFRESHWINDOW | INTUITICKS);
		     start_vsh();

		     /* Restore old IDCMP flags */
		     ModifyIDCMP(con_window, old_idcmp_flags);

		     restore_con_window();
		     CloseFont(con_font);
		  }
		  FreeMem(font_data, (LONG)(MAX_FONT_CHARS * 8));
	       }
	       FreeMem(template_buffer, (LONG)(wb_line_len * 8));
	    }
	    FreeMem(idata, (LONG)sizeof(struct InfoData));
	 }
         FreeMem(fib, (LONG)sizeof(struct FileInfoBlock));
      }
      FreeMem(data_buffer, (LONG)((MAX_EDITOR_NAME_LEN + 1) +
	   (MAX_EDITOR_OPTS_LEN + 1) + MAX_FKEYS * ((MAX_USER_FUNCTION_LEN +
						 1) + (MAX_FKEY_LEN + 1))));
   }
}
