/*
 *  moreHTML
 *  © Dirk Holtwick, 1997
 *  ---------------------
///
    I publish this source, but that doesn't mean that it is  free.  It
    still remains copyrighted by me, Dirk Holtwick, and if you want to
    change the source or add some functions, you first have to get  in
    contact with me and get my permission.

    I regret that the comments and the stile of  the  source  are  not
    very  clear,  but  I  will try to make it more readable and better
    structured. For the compilation I used SAS/C 6.57.

    I need some help reguarding ARexx and Internet Access. Please  get
    in contact with me if you can help me. Thanks.

///                                                   Yours Dirk Holtwick
 */

#define VERS      "1.3"
#define NAME      "moreHTML"
#define TMPREXX   "T:moreHTML_temp_command.rexx"

// #define DEBUG

/// DEBUG
#ifdef DEBUG
// char  debugstr[80];
   extern void KPrintF(...);
   #define DB KPrintF
// #define X KPrintF("Line: %4ld, File: '%s', Press key... ",__LINE__,__FILE__); gets(debugstr);
#else
   #define X
   #define DB ; / ## /
#endif
///
/// Includes
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <rexx/storage.h>
#include <rexx/rxslib.h>

#include <exec/memory.h>
#include <prefs/prefhdr.h>
#include <datatypes/pictureclass.h>
#include <workbench/workbench.h>
#include <libraries/locale.h>
#include <libraries/asl.h>
#include <libraries/gadtools.h>
#include <libraries/mui.h>

#include <proto/rexxsyslib.h>

#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/utility_protos.h>
#include <clib/dos_protos.h>
#include <clib/locale_protos.h>
#include <clib/muimaster_protos.h>
#include <clib/icon_protos.h>

#include <clib/alib_protos.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/locale_pragmas.h>
#include <pragmas/muimaster_pragmas.h>
#include <pragmas/icon_pragmas.h>

#include <dos.h>

#include <mui/htmltext_mcc.h>

#include "dtpic.h"
#include "cb.h"
#include "mylist.h"
#include "mystring.h"
///
/// Compiler Stuff
#ifdef _DCC
#define REG(x) __ ## x
#define ASM
#define SAVEDS __geta4
#else
#define REG(x) register __ ## x
#define ASM    __asm
#define SAVEDS __saveds
#endif
///
/// Definitions
#define MUIM_MainWindow_Finish        0x90a41070
#define MUIM_MainWindow_About         0x90a41071
#define MUIM_MainWindow_Open          0x90a41072
#define MUIM_MainWindow_Iconify       0x90a41073
#define MUIM_MainWindow_Save          0x90a41074
#define MUIM_MainWindow_AddURL        0x90a41075
#define MUIM_MainWindow_BackURL       0x90a41076
#define MUIM_MainWindow_ReloadURL     0x90a41077
#define MUIM_MainWindow_Config        0x90a41078
#define MUIM_MainWindow_Action        0x90a41079
#define MUIM_MainWindow_Find          0x90a4107a
#define MUIM_MainWindow_Rexx          0x90a4107b

#define REQ(text,but)                 MUI_Request(app,obj,0,NULL,but,(char *)text,0)
///
/// Global Vars
char  openurlstr[80];

LONG __stack = 2*8192;

struct Library *MUIMasterBase;
struct Library *GfxBase      ;
struct Library *IntuitionBase;
struct Library *LocaleBase   ;
struct Library *AslBase      ;
struct Library *UtilityBase  ;

Object *win;

extern struct Library *DOSBase;

struct MUI_CustomClass *CL_MainWindow  ;
struct MUI_CustomClass *CL_Dtpic       ;
///
/// Menu
#define RB CHECKIT
#define TG CHECKIT|MENUTOGGLE

enum
{
   MEN_OPEN=1,
   MEN_SAVE,
   MEN_ABOUT,
   MEN_AMUI,
   MEN_PRINT,
   MEN_EDIT,
   MEN_VIEW,
   MEN_HIDE,
   MEN_QUIT,
   MEN_CPBLOCK,
   MEN_CPTEXT,
   MEN_PATEXT,
   MEN_BACK,
   MEN_RELOAD,
   MEN_CONF,
   MEN_MUI,
   MEN_FIND,
   MEN_NEXT,
};

struct NewMenu MainMenu[] =
{
   { NM_TITLE, (STRPTR)"Project"                 , 0 ,0,0,(APTR)0             },
   { NM_ITEM , (STRPTR)"Open"                    ,"O",0,0,(APTR)MEN_OPEN      },
   { NM_ITEM , (STRPTR)"Save as"                 ,"S",0,0,(APTR)MEN_SAVE      },
   { NM_ITEM , (STRPTR)NM_BARLABEL               , 0 ,0,0,(APTR)0             },
   { NM_ITEM , (STRPTR)"Print"                   ,"P",0,0,(APTR)MEN_PRINT     },
   { NM_ITEM , (STRPTR)NM_BARLABEL               , 0 ,0,0,(APTR)0             },
   { NM_ITEM , (STRPTR)"View source"             ,"V",0,0,(APTR)MEN_VIEW      },
   { NM_ITEM , (STRPTR)"Edit source"             ,"E",0,0,(APTR)MEN_EDIT      },
   { NM_ITEM , (STRPTR)NM_BARLABEL               , 0 ,0,0,(APTR)0             },
   { NM_ITEM , (STRPTR)"About"                   ,"?",0,0,(APTR)MEN_ABOUT     },
   { NM_ITEM , (STRPTR)"About MUI"               , 0 ,0,0,(APTR)MEN_AMUI      },
   { NM_ITEM , (STRPTR)NM_BARLABEL               , 0 ,0,0,(APTR)0             },
   { NM_ITEM , (STRPTR)"Hide"                    ,"H",0,0,(APTR)MEN_HIDE      },
   { NM_ITEM , (STRPTR)"Quit"                    ,"Q",0,0,(APTR)MEN_QUIT      },

   { NM_TITLE, (STRPTR)"Edit"                    , 0 ,0,0,(APTR)0             },
   { NM_ITEM , (STRPTR)"Find"                    ,"F",0,0,(APTR)MEN_FIND      },
   { NM_ITEM , (STRPTR)"Find next"               ,"N",0,0,(APTR)MEN_NEXT      },
   { NM_ITEM , (STRPTR)NM_BARLABEL               , 0 ,0,0,(APTR)0             },
   { NM_ITEM , (STRPTR)"Copy block"              ,"C",0,0,(APTR)MEN_CPBLOCK   },
   { NM_ITEM , (STRPTR)"Copy text"               , 0 ,0,0,(APTR)MEN_CPTEXT    },

   { NM_TITLE, (STRPTR)"Navigation"              , 0 ,0,0,(APTR)0             },
   { NM_ITEM , (STRPTR)"Back"                    ,"B",0,0,(APTR)MEN_BACK      },
   { NM_ITEM , (STRPTR)"Reload"                  ,"R",0,0,(APTR)MEN_RELOAD    },

   { NM_TITLE, (STRPTR)"Settings"                , 0 ,0,0,(APTR)0             },
   { NM_ITEM , (STRPTR)"moreHTML"                , 0 ,0,0,(APTR)MEN_CONF      },
   { NM_ITEM , (STRPTR)"MUI"                     , 0 ,0,0,(APTR)MEN_MUI       },

   { NM_END,NULL,0,0,0,(APTR)0 },
};
///
/// Misc Help Functions

LONG xget(Object *obj,ULONG attribute)
{
   LONG x;
   get(obj,attribute,&x);
   return(x);
}

ULONG __stdargs DoSuperNew(struct IClass *cl,Object *obj,ULONG tag1,...)
{
   return(DoSuperMethod(cl,obj,OM_NEW,&tag1,NULL));
}

///
/// Clipboard
int WriteClip(char *string)
{
   struct IOClipReq *ior;

   if (string == NULL)
   {
      puts("No string argument given");
      return(0);
   }
   if (ior = CBOpen(0L))
   {
      if (!(CBWriteFTXT(ior,string)))
        printf("Error writing to clipboard: io_Error = %ld\n",ior->io_Error);
      CBClose(ior);
   }
   else
      puts("Error opening clipboard.device");
   return(0);
}
///

// Structures

/// struct URLlist
struct URLlist
{
   struct   URLlist
            *next;
   char     *url;
   ULONG    yoff;
};
///
/// struct Config_Data
struct Config_Data
{
   char  viewsource[80];
   char  printtext[80];
   char  editsource[80];
   char  openurl[80];
};
///
/// struct Tool_Data
struct Tool_Data
{
   struct   Tool_Data
            *next;
   char     *command;
   char     *help;
};
///
/// struct MainWindow_Data
struct MainWindow_Data
{
   Object   *win;
   Object   *file;
   Object   *html;
   Object   *scroll;
   Object   *infoline;
   Object   *toolbar;
   Object   *tool[4];

   char     searchstr[256];
   ULONG    searchpos;

   char     path[256];

   struct   Config_Data
            cfg;

   struct   URLlist
            *urllist;

   // Toolbar
   struct   MyList
            *tools;
};
///

// Rexx

/*
/// Data
#define  REXX_RETURN_ERROR ((struct RexxMsg *)-1L)
#define  AREXXCONTEXT   struct ARexxContext *

struct   ARexxContext
{
   struct   MsgPort
            *ARexxPort;       // The port messages come in at...
   long     Outstanding;      // The count of outstanding ARexx messages...
   char     PortName[24];     // The port name goes here...
   char     ErrorName[28];    // The name of the <base>.LASTERROR...
   char     Extension[8];     // Default file name extension...
}
adata;
///
/// GetARexxMsg
struct RexxMsg *GetARexxMsg(AREXXCONTEXT RexxContext)
{
register struct   RexxMsg  *tmp=NULL;
register    short flag;

   if (RexxContext)
       if (tmp=(struct RexxMsg *)GetMsg(RexxContext->ARexxPort))
   {
      if (tmp->rm_Node.mn_Node.ln_Type==NT_REPLYMSG)
      {
         flag=FALSE;
         if (tmp->rm_Result1) flag=TRUE;

         DeleteArgstring(tmp->rm_Args[0]);
         DeleteRexxMsg(tmp);
         RexxContext->Outstanding-=1;

         tmp=flag ? REXX_RETURN_ERROR : NULL;
      }
   }
   return(tmp);
}
///
/// ReplyARexxMsg
void ReplyARexxMsg(AREXXCONTEXT RexxContext,struct RexxMsg *rmsg,
         char *RString,LONG Error)
{
   if (RexxContext) if (rmsg) if (rmsg!=REXX_RETURN_ERROR)
   {
      rmsg->rm_Result2=0;
      if (!(rmsg->rm_Result1=Error))
      {
         if (rmsg->rm_Action & (1L << RXFB_RESULT)) if (RString)
         {
            rmsg->rm_Result2=(LONG)CreateArgstring(RString,
                     (LONG)strlen(RString));
         }
      }

      ReplyMsg((struct Message *)rmsg);
   }
}
///
/// SetARexxLastError
short SetARexxLastError(AREXXCONTEXT RexxContext,struct RexxMsg *rmsg,
         char *ErrorString)
{
register short OkFlag=FALSE;

   if (RexxContext) if (rmsg) if (CheckRexxMsg((struct Message *)rmsg))
   {
      if (!SetRexxVar((struct Message *)rmsg,RexxContext->ErrorName,ErrorString,
                  (long)strlen(ErrorString)))
      {
         OkFlag=TRUE;
      }
   }
   return(OkFlag);
}
///
/// SendARexxMsg
short SendARexxMsg(AREXXCONTEXT RexxContext,char *RString,
         short StringFile)
{
   register struct   MsgPort  *RexxPort;
   register struct   RexxMsg  *rmsg;
   register    short flag=FALSE;

   if (RexxContext) if (RString)
   {
      if (rmsg=CreateRexxMsg(RexxContext->ARexxPort,
               NULL, //RexxContext->Extension,
               RexxContext->PortName))
      {
         rmsg->rm_Action=RXCOMM | (StringFile ?
                     (1L << RXFB_STRING):0);
         if (rmsg->rm_Args[0]=CreateArgstring(RString,
                     (LONG)strlen(RString)))
         {
            Forbid();
            if (RexxPort=FindPort(RXSDIR))
            {
               PutMsg(RexxPort,(struct Message *)rmsg);
               RexxContext->Outstanding+=1;
               flag=TRUE;
            }
            else
            {
               DeleteArgstring(rmsg->rm_Args[0]);
               DeleteRexxMsg(rmsg);
            }
            Permit();
         }
         else DeleteRexxMsg(rmsg);
      }
   }
   return(flag);
}
///
/// InitARexx
void InitARexx(AREXXCONTEXT data, char *portname)
{
   DB("Init ARexx\n");

   data->Outstanding=0;
   stccpy(data->Extension, "rexx", sizeof(data->Extension));
   stccpy(data->PortName, portname, sizeof(data->PortName));
   strcpy(data->ErrorName, data->PortName);
   strcat(data->ErrorName, ".LASTERROR");
   data->ARexxPort=FindPort(data->PortName);
}
///
/// FreeARexx
void FreeARexx(AREXXCONTEXT RexxContext)
{
   register struct RexxMsg  *rmsg;

   DB("Free ARexx\n");

   RexxContext->PortName[0]='\0';

   while (RexxContext->Outstanding)
   {
      DB("  Out...\n");

      WaitPort(RexxContext->ARexxPort);
      while (rmsg=GetARexxMsg(RexxContext))
      {
         if (rmsg!=REXX_RETURN_ERROR)
         {
//            SetARexxLastError(RexxContext,rmsg,
//                      "99: Port Closed!");
            ReplyARexxMsg(RexxContext,rmsg,
                  NULL,100);
         }
      }
   }
}
///
*/

// Toolbar

/// CreateToolbar
void CreateToolbar(struct MainWindow_Data *data)
{
   FILE     *f;
   static   char
            inbuf[1024],
            buf[1024];
//          *str;
   struct   RDArgs
            rda;
   BOOL     error = TRUE,
            textmode = FALSE,
            virgin = TRUE,
            horiz = TRUE;

   struct
   {
      char     *pos;
      ULONG    mode;
      ULONG    space;
      char     *text;
      char     *command;
      ULONG    script;
      char     *key;
      char     *image;
      char     *help;
   } arr;

   data->toolbar = data->tool[0];

   if(data->tools = MyCreateList(sizeof(struct Tool_Data), 12))
   if(f = fopen("PROGDIR:config/moreHTML.toolbar.config","r"))
   {
      while(!feof(f))
      {
         fgets(inbuf, sizeof(inbuf), f);
         buf[strlen(inbuf)-1] = 0;

         if((*stpblk(inbuf) != '#') && (*stpblk(inbuf) != NULL))
         {
            error = FALSE;

            memset(&rda, 0, sizeof(struct RDArgs));
            memset(&arr, 0, sizeof(arr));

            rda.RDA_Source.CS_Buffer = inbuf;
            rda.RDA_Source.CS_Length = strlen(inbuf);

            ReadArgs("POS=POSITION/K,TEXTMODE/S,SPACE/S,TEXT/K,COMMAND/K,SCRIPT/S,KEY/K,IMAGE/K,HELP/K",(LONG *)&arr,&rda);

            // Some definitions that have to come before the button definitions
            if(virgin)
            {
               if(arr.pos)
               {
                  if(!stricmp(arr.pos,"left"))
                  {
                     data->toolbar = data->tool[2];
                     horiz = FALSE;
                  }
                  else if(!stricmp(arr.pos,"right"))
                  {
                     data->toolbar = data->tool[3];
                     horiz = FALSE;
                  }
                  else if(!stricmp(arr.pos,"bottom"))
                     data->toolbar = data->tool[1];
               }
               if(arr.mode) textmode=TRUE;
            }

            // Kill old contents
            if((arr.space || arr.text) && virgin)
            {
               struct   List
                        *childlist;
               Object   *cstate;
               Object   *child;

               if(childlist = (void *)xget(data->toolbar, MUIA_Group_ChildList))
               {
                  cstate = (Object *)childlist->lh_Head;
                  while (child = NextObject(&cstate))
                     DoMethod(data->toolbar, OM_REMMEMBER, child);
               }
               virgin = FALSE;
            }

            // Create space
            if(arr.space)
            {
               if(horiz)
                  DoMethod (data->toolbar, OM_ADDMEMBER, HSpace(0));
               else
                  DoMethod (data->toolbar, OM_ADDMEMBER, VSpace(0));
            }

            // Create button
            else if(arr.text)
            {
               Object *obj;
               struct Tool_Data *t;

               // Buffer the important strings
               // Uses private functions
               t = MyAddItem(data->tools);
               t->command = MyAllocString(arr.command);
               t->help    = MyAllocString(arr.help);

               if(textmode)
               {
                  DoMethod (data->toolbar, OM_ADDMEMBER,
                     obj = TextObject,
                        ButtonFrame,
                        MUIA_Text_Contents, arr.text,
                        MUIA_Text_PreParse, "\33c",
                        MUIA_Text_HiChar  , *arr.key,
                        MUIA_ControlChar  , *arr.key,
                        MUIA_InputMode    , MUIV_InputMode_RelVerify,
                        MUIA_Background   , MUII_ButtonBack,
                        MUIA_CycleChain   , TRUE,
                        MUIA_ShortHelp    , t->help,
                        End
                  );
               }
               else
               {
                  DoMethod (data->toolbar, OM_ADDMEMBER,
                     obj = DtpicObject,
                        ImageButtonFrame,
                        MUIA_CycleChain           , 1,
                        MUIA_InputMode            , MUIV_InputMode_RelVerify,
                        MUIA_Dtpic_Name           , arr.image,
                        MUIA_ShortHelp            , t->help,
                        MUIA_ControlChar          , *arr.key,
                        End
                  );
               }

               DoMethod(obj, MUIM_Notify, MUIA_Pressed, FALSE,
                  data->win,3,MUIM_MainWindow_Rexx,t->command,arr.script);
            }

            FreeArgs(&rda);
         }
      }
      fclose(f);
   }
   else
   {
      puts("Couldn't open toolbar config file.");
   }

   if(error)
      DoMethod (data->toolbar, OM_ADDMEMBER,
         HSpace(0)
      );
}
///
/// DisposeToolbar
void DisposeToolbar(struct MainWindow_Data *data)
{
   struct Tool_Data *t;

   t = (void *)data->tools->first;
   while(t)
   {
      MyFreeString(t->command);
      MyFreeString(t->help);
      t=t->next;
   }

   MyDisposeList(data->tools);
}
///

// MainWindow

/// OpenURLHook
__saveds ULONG __asm OpenURL(register __a0 struct Hook *h, register __a2 Object *obj, register __a1 struct{ char *URL; char *TmpFilename; } *msg)
{
// struct MainWindow_Data *data = INST_DATA(OCLASS(obj), obj);
// char   buf[120];

// sprintf(buf, openurlstr, msg->URL, msg->LocalFile);

   puts(msg->TmpFilename);
   strcpy(msg->TmpFilename, "work:www/index.html");
   puts(msg->TmpFilename);
// if(buf[0]) system(buf);
   return(TRUE);
}
///
/// AppMsgFunc
SAVEDS ASM LONG AppMsgFunc(REG(a2) APTR obj, REG(a1) struct AppMessage **x)
{
   struct WBArg *ap;
   struct AppMessage *amsg = *x;
   static char buf[256];

   if(amsg->am_NumArgs)
   {
      ap=amsg->am_ArgList;
      NameFromLock(ap->wa_Lock,buf,sizeof(buf));
      AddPart(buf,ap->wa_Name,sizeof(buf));
      set(obj,MUIA_HTMLtext_URL,buf);
   }

   return(0);
}
///
/// SaveHTML
void SaveHTML(struct MainWindow_Data *data, char *name)
{
   if(name)
   {
      char  *text;
      FILE  *f;

      get(data->html, MUIA_HTMLtext_Contents, &text);
      if(f=fopen(name,"w"))
      {
         fwrite(text,strlen(text),1,f);
         fclose(f);
      }
   }
}
///
/// MainWindow_Rexx
ULONG MainWindow_Rexx(struct IClass *cl,Object *obj,struct {ULONG MethodID; char *command; ULONG script;} *msg)
{
//   struct MainWindow_Data *data = INST_DATA(cl,obj);

   DB("Command: %s, Script: %ld\n",msg->command,!msg->script);
/*
   SendARexxMsg(&adata,msg->command,!msg->script);
*/
   {
      char     *name, cmd[256];
      FILE     *f;
      Object   *app = (Object *)xget(obj,MUIA_ApplicationObject);

      name = TMPREXX;
      if(f = fopen(name,"w"))
      {
         fprintf(f,
            "/* Tmpfile */\n"
            "address %s %s",
            ((char *)xget(app,MUIA_Application_Base)),
            msg->command
         );
         fclose(f);

         sprintf(cmd,"run <>nil: sys:rexxc/rx %s",name);
         system(cmd);
      }
   }

   return(0);
}
///
/// MainWindow_Config
ULONG MainWindow_Config(struct IClass *cl,Object *obj,struct {ULONG MethodID; ULONG justget;} *msg)
{
   struct   MainWindow_Data *data = INST_DATA(cl,obj);
   Object   *app = (Object *)xget(obj,MUIA_ApplicationObject);
   char     *h;
   ULONG    d;

   Object
      *win,
      *showtoolbar,
      *showinfoline,
      *viewsource,
      *editsource,
      *printtext;
//    *openurl;

   enum
   {
      OBJ_showtoolbar = 1,
      OBJ_showinfoline,
      OBJ_viewsource,
      OBJ_editsource,
      OBJ_printtext,
      OBJ_openurl,
   };

   static const char *titles[] =
   {
      "Misc",
      "Commands",
      NULL
   };

   set(app,MUIA_Application_Sleep,TRUE);  // disable other windows

   win =
      WindowObject,
         MUIA_Window_Title, "Settings",
         MUIA_Window_ID   , MAKE_ID('C','O','N','F'),

         WindowContents, VGroup,

            Child, RegisterObject,
               MUIA_Register_Titles, titles,

               // DISPLAY
               Child, ColGroup(2),
                  Child, LLabel("Show _tool bar"),
                  Child, showtoolbar = KeyCheckMark(TRUE,'t'),
                  Child, LLabel("Show _info line"),
                  Child, showinfoline = KeyCheckMark(TRUE,'i'),
                  End,

               // FUNCTIONS
               Child, ColGroup(2),
                  Child, VSpace(0),
                  Child, VSpace(0),
/*
                  Child, LLabel("Open URL"),
                  Child, openurl = StringObject,
                     StringFrame,
                     MUIA_CycleChain, 1,
                     MUIA_ObjectID, OBJ_openurl,
                     MUIA_String_Contents, "geturl %s %s",
                     MUIA_ShortHelp,
                        "Command to be used to load page and data\n"
                        "of an to HTMLtext unknown protocol.\n"
                        "First '%s' stands for the URL and the\n"
                        "second '%s' for the file where to write\n"
                        "data to.",
                     End,
                  Child, VSpace(0),
                  Child, VSpace(0),
*/
                  Child, LLabel("Print text"),
                  Child, printtext = StringObject,
                     StringFrame,
                     MUIA_CycleChain, 1,
                     MUIA_ObjectID, OBJ_printtext,
                     MUIA_String_Contents, "httx %s prt: ansi",
                     MUIA_ShortHelp,
                        "Command to be used to print the\n"
                        "contents of the current HTML file.\n"
                        "One '%s' has to be used!",
                     End,
                  Child, LLabel("View source"),
                  Child, viewsource = StringObject,
                     StringFrame,
                     MUIA_CycleChain, 1,
                     MUIA_ObjectID, OBJ_viewsource,
                     MUIA_String_Contents, "more %s",
                     MUIA_ShortHelp,
                        "Command to be used to display the\n"
                        "source of the current HTML file.\n"
                        "One '%s' has to be used!",
                     End,
                  Child, LLabel("Edit source"),
                  Child, editsource = StringObject,
                     StringFrame,
                     MUIA_CycleChain, 1,
                     MUIA_ObjectID, OBJ_editsource,
                     MUIA_String_Contents, "ed %s",
                     MUIA_ShortHelp,
                        "Command to be used to edit the\n"
                        "source of the current HTML file.\n"
                        "One '%s' has to be used!",
                     End,
/*
                  Child, printtext = LLabel("On Double-Click"),
                  Child, StringObject,
                     StringFrame,
                     MUIA_CycleChain, 1,
                     MUIA_ObjectID, OBJ_printtext,
                     MUIA_String_Contents, "rx findword.rexx",
                     MUIA_ShortHelp,
                        "Command to be used to print the\n"
                        "contents of the current HTML file.\n"
                        "One '\%s' has to be used!",
                     End,
*/
                  Child, VSpace(0),
                  Child, VSpace(0),
                  End,

               End,
            End,
         End;

   if (win)                               // ok ?
   {
      DoMethod(app,OM_ADDMEMBER,win);    // add window...
      DoMethod(win,MUIM_Notify,MUIA_Window_CloseRequest,TRUE ,
         app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);

      set(showtoolbar,   MUIA_ObjectID, OBJ_showtoolbar);
      set(showtoolbar,   MUIA_CycleChain, 1);
      set(showinfoline,  MUIA_ObjectID, OBJ_showinfoline);
      set(showinfoline,  MUIA_CycleChain, 1);

      DoMethod(app,MUIM_Application_Load, MUIV_Application_Load_ENVARC);

      // Just get the config datas
      if(!msg->justget)
      {

         set(win,MUIA_Window_Open,TRUE);    // and open it

         {
            ULONG sigs = 0;

            while (DoMethod(app,MUIM_Application_NewInput,&sigs) != MUIV_Application_ReturnID_Quit)
            {
               if (sigs)
               {
                  sigs = Wait(sigs | SIGBREAKF_CTRL_C);
                  if (sigs & SIGBREAKF_CTRL_C) break;
               }
            }
         }

         set(win,MUIA_Window_Open,FALSE);   // Close window

         DoMethod(app,MUIM_Application_Save, MUIV_Application_Save_ENVARC);
      }

      // Read out the config datas
      get(showtoolbar, MUIA_Selected, &d);
      set(data->toolbar, MUIA_ShowMe, d);

      get(showinfoline, MUIA_Selected, &d);
      set(data->infoline, MUIA_ShowMe, d);

      get(viewsource, MUIA_String_Contents, &h);
      strcpy(data->cfg.viewsource, h);

      get(editsource, MUIA_String_Contents, &h);
      strcpy(data->cfg.editsource, h);

      get(printtext, MUIA_String_Contents, &h);
      strcpy(data->cfg.printtext, h);

/*
      get(openurl, MUIA_String_Contents, &h);
      strcpy(data->cfg.openurl, h);
      strcpy(openurlstr, h);
*/
      // Remove window
      DoMethod(app,OM_REMMEMBER,win);    // remove

      MUI_DisposeObject(win);            // and kill it
   }
   else puts("Couldn't open config window.");

   set(app,MUIA_Application_Sleep,FALSE); // wake up the application
   return(0);
}
///
/// MainWindow_Iconify
ULONG MainWindow_Iconify(struct IClass *cl,Object *obj,struct Msg *msg)
{
// struct MainWindow_Data *data = INST_DATA(cl,obj);

   set((Object *)xget(obj,MUIA_ApplicationObject),MUIA_Application_Iconified,TRUE);

   return(0);
}
///
/// MainWindow_Finish
ULONG MainWindow_Finish(struct IClass *cl,Object *obj,struct Msg *msg)
{
//   struct MainWindow_Data *data = INST_DATA(cl,obj);
   DoMethod((Object *)xget(obj,MUIA_ApplicationObject),MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
   return(0);
}
///
/// MainWindow_About
ULONG MainWindow_About(struct IClass *cl,Object *obj,Msg msg)
{
   Object *app = (Object *)xget(obj,MUIA_ApplicationObject);
   static const char AboutText[] =
      "\33b\33c" NAME
      "\33n\n\33cVersion %s\n\33c%s\n\n\033c%s\n\n\33c\33i"
      "This software is subject to the\n"
      "\"Standard Amiga FD-Software Copyright Note\".\n"
      "It is GIFTWARE as defined in paragraph 4g.\n"
      "For more information please read\n"
      "\"AFD-COPYRIGHT\" (Version 1 or higher).\n"
      "If you like and use it, please send something."
      "\33n\n\n\33cARexx-Port: %s";

   MUI_Request(app,obj,0,NULL,"*_OK",(char *)AboutText,
      ((char *)xget(app,MUIA_Application_Version))+7+strlen(NAME),
      ((char *)xget(app,MUIA_Application_Copyright)),
      ((char *)xget(app,MUIA_Application_Description)),
      ((char *)xget(app,MUIA_Application_Base)));
   return(0);
}
///
/// MainWindow_AddURL
ULONG MainWindow_AddURL(struct IClass *cl,Object *obj,struct {ULONG MethodID; char *url;} *msg)
{
   struct MainWindow_Data *data = INST_DATA(cl,obj);
   struct URLlist *act;

   get(data->html, MUIA_HTMLtext_URL, &msg->url);
   set(data->file, MUIA_String_Contents, msg->url);

   if(msg->url && *msg->url)
   {
      if(act = AllocVec(sizeof(struct URLlist), 0))
      {
         act->next = data->urllist;
         data->urllist = act;
         get(data->html, MUIA_Virtgroup_Top, &act->yoff);

         act->url = MyAllocString(msg->url);
      }

      data->searchpos = 0;
   }

   return(0);
}
///
/// MainWindow_BackURL
ULONG MainWindow_BackURL(struct IClass *cl,Object *obj,Msg msg)
{
   struct MainWindow_Data *data = INST_DATA(cl,obj);
   struct URLlist *next, *old;

   if(data->urllist)
   {
      // Skip recent
      next = data->urllist->next;
      MyFreeString(data->urllist->url);
      FreeVec(data->urllist);
      data->urllist = next;

      if(data->urllist)
      {
         // Kill actual, because will be readded
         old = data->urllist;
         data->urllist = data->urllist->next;

         set(data->html, MUIA_HTMLtext_URL,  old->url);
         set(data->html, MUIA_Virtgroup_Top, old->yoff);

         MyFreeString(old->url);
         FreeVec(old);
      }
   }
   return(0);
}
///
/// MainWindow_ReloadURL
ULONG MainWindow_ReloadURL(struct IClass *cl,Object *obj,Msg msg)
{
   struct MainWindow_Data *data = INST_DATA(cl,obj);

   DoMethod(data->html, MUIM_HTMLtext_Reload);
   return(0);
}
///
/// IntuiMsgFunc
SAVEDS ASM VOID IntuiMsgFunc(REG(a1) struct IntuiMessage *imsg,REG(a2) struct FileRequester *req)
{
   if (imsg->Class==IDCMP_REFRESHWINDOW)
      DoMethod(req->fr_UserData,MUIM_Application_CheckRefresh);
}
///
/// getfilename
char *getfilename(char *title,BOOL save, char *path)
{
   static char buf[512];
   struct FileRequester *req;
   struct Window *w;
   static LONG left=-1,top=-1,width=-1,height=-1;
   Object *app = (Object *)xget(win,MUIA_ApplicationObject);
   char *res = NULL;
   static const struct Hook IntuiMsgHook = { { 0,0 },(VOID *)IntuiMsgFunc,NULL,NULL };

   get(win,MUIA_Window_Window,&w);
   if (left==-1)
   {
      left   = w->LeftEdge+w->BorderLeft+2;
      top    = w->TopEdge+w->BorderTop+2;
      width  = w->Width-w->BorderLeft-w->BorderRight-4;
      height = w->Height-w->BorderTop-w->BorderBottom-4;
   }

   if (req=MUI_AllocAslRequestTags(ASL_FileRequest,
      ASLFR_Window, w,
      ASLFR_TitleText, title,
      ASLFR_InitialLeftEdge, left,
      ASLFR_InitialTopEdge , top,
      ASLFR_InitialWidth   , width,
      ASLFR_InitialHeight  , height,
      ASLFR_InitialDrawer  , path,
      ASLFR_InitialPattern , "#?.(html|htm)",
      ASLFR_DoSaveMode     , save,
      ASLFR_DoPatterns     , TRUE,
      ASLFR_RejectIcons    , TRUE,
      ASLFR_UserData       , app,
      ASLFR_IntuiMsgFunc   , &IntuiMsgHook,
      TAG_DONE))
   {
      set(app,MUIA_Application_Sleep,TRUE);
      if (MUI_AslRequestTags(req,TAG_DONE))
      {
         if (*req->fr_File)
         {
            res = buf;
            stccpy(path,req->fr_Drawer,255);
            stccpy(buf,req->fr_Drawer,sizeof(buf));
            AddPart(buf,req->fr_File,sizeof(buf));
         }
         left   = req->fr_LeftEdge;
         top    = req->fr_TopEdge;
         width  = req->fr_Width;
         height = req->fr_Height;
      }
      MUI_FreeAslRequest(req);
      set(app,MUIA_Application_Sleep,FALSE);
   }
   return(res);
}
///
/// MainWindow_Action
enum
{
   ACTION_clipblock,
   ACTION_clipsrc,
   ACTION_print,
   ACTION_viewsrc,
   ACTION_editsrc,
   ACTION_geturl,
};

ULONG MainWindow_Action(struct IClass *cl,Object *obj,struct {ULONG MethodID; ULONG mode;} *msg)
{
   struct   MainWindow_Data *data = INST_DATA(cl,obj);
   char     buf[120], *text, tmpname[60];

   switch(msg->mode)
   {
      // Clip block
      case ACTION_clipblock:
         get(data->html, MUIA_HTMLtext_Block, &text);
         WriteClip(text);
         break;

      // Clip source
      case ACTION_clipsrc:
         get(data->html, MUIA_HTMLtext_Contents, &text);
         WriteClip(text);
         break;

      // Print text
      case ACTION_print:
         tmpnam(tmpname);
         SaveHTML(data, tmpname);
         sprintf(buf, data->cfg.printtext, tmpname);
         if(buf[0]) system(buf);
         remove(tmpname);
         break;

      // View source
      case ACTION_viewsrc:
         tmpnam(tmpname);
         SaveHTML(data, tmpname);
         sprintf(buf, data->cfg.viewsource, tmpname);
         if(buf[0]) system(buf);
         remove(tmpname);
         break;

      // Edit source
      case ACTION_editsrc:
         if(data->urllist)
         {
            sprintf(buf, data->cfg.editsource, data->urllist->url);
            if(buf[0]) system(buf);
            DoMethod(obj, MUIM_MainWindow_ReloadURL, 0);
         }
         break;

      // Get URL
      case ACTION_geturl:
         {
            ULONG url;

            get(data->html, MUIA_HTMLtext_URL, &url);
            return(url);
         }
         break;
   }
   return(0);
}
///
/// MainWindow_Find
enum
{
   FIND_new = 1,
   FIND_word,
   FIND_next,
   FIND_first
};

ULONG Search(struct MainWindow_Data *data, STRPTR searchstr, ULONG pos, ULONG flags)
{
   struct MUIS_HTMLtext_Element *el; //, *ell;
// Object *app = (Object *)xget(data->html,MUIA_ApplicationObject);
// char  *str;

   if(searchstr && *searchstr)
   {
//    set(app, MUIA_Application_Sleep, TRUE);
      get(data->html, MUIA_HTMLtext_ElementList, &el);
      while(el)
      {
         if(!strnicmp(MACRO_HTMLtext_GetText(el), searchstr, strlen(searchstr)))
         {
            if(pos)
               pos--;
            else
            {
               DoMethod(data->html, MUIM_HTMLtext_Mark, el, el);
               DoMethod(data->html, MUIM_HTMLtext_Jump, el);
               return(TRUE);
            }
         }
         el = el->next;
      }
//    set(app, MUIA_Application_Sleep, FALSE);
   }

   return(FALSE);
}

ULONG MainWindow_Find(struct IClass *cl,Object *obj,struct {ULONG MethodID; ULONG mode; char *str;} *msg)
{
   Object *app = (Object *)xget(obj,MUIA_ApplicationObject);
   struct MainWindow_Data *data = INST_DATA(cl,obj);

   switch(msg->mode)
   {
      case FIND_new:
         // Open window and ask
         {
            Object   *win, *searchstr, *start;
            char     *str;

            set(app,MUIA_Application_Sleep,TRUE);  // disable other windows

            win =
               WindowObject,
                  MUIA_Window_Title, "Find",
                  MUIA_Window_ID   , MAKE_ID('F','I','N','D'),

                  WindowContents, VGroup,
                     Child, LLabel("Find this string:"),
                     Child, searchstr = StringObject,
                        StringFrame,
                        MUIA_CycleChain, 1,
                        MUIA_String_AdvanceOnCR, TRUE,
                        MUIA_String_Contents, data->searchstr,
                        MUIA_ShortHelp, "Will find all words in the text\nbeginning with this string",
                        End,
                     Child, start = SimpleButton("_Start"),
                     End,
                  End;

            if (win)                               // ok ?
            {
               DoMethod(app,OM_ADDMEMBER,win);    // add window...
               DoMethod(win,MUIM_Notify,MUIA_Window_CloseRequest,TRUE ,
                  app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
               DoMethod(start, MUIM_Notify, MUIA_Pressed, FALSE,
                  app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);

               set(start,MUIA_CycleChain, 1);
               set(win,MUIA_Window_Open,TRUE);    // and open it
               set(win,MUIA_Window_ActiveObject, searchstr);

               {
                  ULONG sigs = 0;

                  while (DoMethod(app,MUIM_Application_NewInput,&sigs) != MUIV_Application_ReturnID_Quit)
                  {
                     if (sigs)
                     {
                        sigs = Wait(sigs | SIGBREAKF_CTRL_C);
                        if (sigs & SIGBREAKF_CTRL_C) break;
                     }
                  }
               }

               set(win,MUIA_Window_Open,FALSE);   // Close window

               get(searchstr, MUIA_String_Contents, &str);
               stccpy(data->searchstr, str, sizeof(data->searchstr));

               // Remove window
               DoMethod(app,OM_REMMEMBER,win);    // remove

               MUI_DisposeObject(win);            // and kill it
            }
            else puts("Couldn't open search window.");

            set(app,MUIA_Application_Sleep,FALSE); // wake up the application
         }

      case FIND_first:
         data->searchpos = 0;
         break;

      case FIND_word:
         // Take word from string (AREXX)
         stccpy(data->searchstr, msg->str, sizeof(data->searchstr));
         data->searchpos = 0;
         break;

   }

   // Suchen und erhöhen
   if(!Search(data, data->searchstr, data->searchpos++, 0))
   {
      // Am Ende angelang wieder das erste zeigen
      if(data->searchpos)
      {
         data->searchpos = 0;
         Search(data, data->searchstr, data->searchpos++, 0);
      }
      else REQ("String can't be found!","*_OK");
   }

   return(0);
}
///
/// MainWindow_Open
ULONG MainWindow_Open(struct IClass *cl,Object *obj,struct {ULONG MethodID; char *name;} *msg)
{
   struct MainWindow_Data *data = INST_DATA(cl,obj);
   char *name;

   if(msg->name)
   {
      if(*msg->name == 0)
         get(data->file, MUIA_String_Contents, &name);
      else
         name = msg->name;
   }
   else
   {
      name = getfilename("Select local file",FALSE,data->path);
   }

   if(name)
   {
      set(data->html, MUIA_HTMLtext_URL, name);
      set(obj, MUIA_Window_ActiveObject, data->html);
   }

   return(0);
}
///
/// MainWindow_Save
ULONG MainWindow_Save(struct IClass *cl,Object *obj,struct {ULONG MethodID; char *name;} *msg)
{
   struct MainWindow_Data *data = INST_DATA(cl,obj);
   char *name;

   if(msg->name)
   {
      name = msg->name;
   }
   else
   {
      name = getfilename("Select local file",TRUE,data->path);
   }

   SaveHTML(data, name);
   return(0);
}
///
/// MainWindow_Dispose
ULONG MainWindow_Dispose(struct IClass *cl,Object *obj,Msg msg)
{
   struct MainWindow_Data *data = INST_DATA(cl,obj);
   struct URLlist *act, *next;

   DB("Dispose\n");

   // Free url list
   act = data->urllist;
   while(act)
   {
      next = act->next;
      MyFreeString(act->url);
      FreeVec(act);
      act = next;
   }

   DisposeToolbar(data);

   DB("End Dispose\n");

   return(DoSuperMethodA(cl,obj,msg));
}
///
/// MainWindow_New
ULONG MainWindow_New(struct IClass *cl,Object *obj,struct opSet *msg)
{
   Object *strip;
   struct MainWindow_Data tmp = {0};
// static const struct Hook OpenURLHook = { { NULL,NULL },(VOID *)OpenURL ,NULL,NULL };
   static const struct Hook AppMsgHook = { { NULL,NULL },(VOID *)AppMsgFunc,NULL,NULL };

   tmp.html = HTMLtextObject,
      TextFrame,
//    MUIA_HTMLtext_OpenURLHook, &OpenURLHook,
      End;

   // To save the MUI custom class directory structure, we look
   // for the class also in "libs/mui" of the PROGDIR:
   if(!tmp.html)
   {
      tmp.html =  MUI_NewObject("PROGDIR:libs/mui/HTMLtext.mcc",
         TextFrame,
//       MUIA_HTMLtext_OpenURLHook, &OpenURLHook,
         End;
   }

   if (obj = (Object *)DoSuperNew(cl,obj,
         MUIA_Window_Title, "MoreHTML © Dirk Holtwick, 1997",
         MUIA_Window_ID   , MAKE_ID('H','T','M','L'),
         MUIA_Window_UseRightBorderScroller, TRUE,
         MUIA_Window_UseBottomBorderScroller, TRUE,
         MUIA_Window_Menustrip, strip = MUI_MakeObject(MUIO_MenustripNM,MainMenu,0),
         MUIA_Window_AppWindow, TRUE,

         WindowContents, HGroup,
            Child, tmp.tool[2] = VGroup,
               MUIA_VertWeight, 1,
               Child, VSpace(0),
               End,
            Child, VGroup,
               Child, tmp.tool[0] = HGroup,
                  Child, HSpace(0),
                  End,

               // Infoline
               Child, tmp.infoline = HGroup,
                  Child, tmp.file = StringObject,
                     StringFrame,
                     MUIA_CycleChain, 1,
                     End,
                  End,

               // HTML object
               Child, tmp.scroll = ScrollgroupObject,
                  MUIA_CycleChain, 1,
                  MUIA_Scrollgroup_UseWinBorder, TRUE,
                  MUIA_Scrollgroup_Contents, tmp.html,       // 'html' created above
                  End,

               Child, tmp.tool[1] = HGroup,
                  Child, HSpace(0),
                  End,
               End,
            Child, tmp.tool[3] = VGroup,
               MUIA_VertWeight, 1,
               Child, VSpace(0),
               End,
            End,

         TAG_MORE,msg->ops_AttrList))
   {
      struct MainWindow_Data *data = INST_DATA(cl,obj);

      *data = tmp;

      data->win = obj;

      // Add toolbar
      CreateToolbar(data);

      // Methods
      DoMethod(obj      ,MUIM_Notify,MUIA_Window_CloseRequest,TRUE ,obj,2,MUIM_MainWindow_Finish, 0);

      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_ABOUT    ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,1,MUIM_MainWindow_About);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_OPEN     ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,2,MUIM_MainWindow_Open,0);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_SAVE     ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,2,MUIM_MainWindow_Save,0);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_HIDE     ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,1,MUIM_MainWindow_Iconify);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_QUIT     ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,2,MUIM_MainWindow_Finish,0);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_FIND     ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,3,MUIM_MainWindow_Find,FIND_new,0);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_NEXT     ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,3,MUIM_MainWindow_Find,FIND_next,0);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_CPTEXT   ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,2,MUIM_MainWindow_Action,ACTION_clipsrc);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_CPBLOCK  ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,2,MUIM_MainWindow_Action,ACTION_clipblock);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_PRINT    ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,2,MUIM_MainWindow_Action,ACTION_print);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_VIEW     ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,2,MUIM_MainWindow_Action,ACTION_viewsrc);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_EDIT     ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,2,MUIM_MainWindow_Action,ACTION_editsrc);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_BACK     ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,1,MUIM_MainWindow_BackURL);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_RELOAD   ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,1,MUIM_MainWindow_ReloadURL);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_CONF     ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         obj,1,MUIM_MainWindow_Config, FALSE);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_AMUI     ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         MUIV_Notify_Application,2,MUIM_Application_AboutMUI,obj);
      DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_MUI      ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,
         MUIV_Notify_Application,2,MUIM_Application_OpenConfigWindow,0);

      // URL
      DoMethod(data->html,MUIM_Notify,MUIA_HTMLtext_URL,MUIV_EveryTime,
         obj,2,MUIM_MainWindow_AddURL,MUIV_TriggerValue);

      // Title
      DoMethod(data->html,MUIM_Notify,MUIA_HTMLtext_Title,MUIV_EveryTime,
         obj,3,MUIM_Set,MUIA_Window_Title,MUIV_TriggerValue);

      // String
      DoMethod(data->file, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime,
         obj,2,MUIM_MainWindow_Open,"");

      // App Msg
      DoMethod(data->html,MUIM_Notify,MUIA_AppMessage,MUIV_EveryTime,
         data->html,3,MUIM_CallHook,&AppMsgHook,MUIV_TriggerValue);

      set(obj,MUIA_Window_ActiveObject,data->scroll);
      set(obj,MUIA_Window_DefaultObject,data->scroll);

      data->urllist = 0;

      return((ULONG)obj);
   }
   return(0);
}
///
/// MainWindow_Dispatcher
SAVEDS ASM ULONG MainWindow_Dispatcher(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
{
   switch (msg->MethodID)
   {
      case OM_NEW                   : return(MainWindow_New       (cl,obj,(APTR)msg));
      case OM_DISPOSE               : return(MainWindow_Dispose   (cl,obj,(APTR)msg));
      case MUIM_MainWindow_Finish   : return(MainWindow_Finish    (cl,obj,(APTR)msg));
      case MUIM_MainWindow_Iconify  : return(MainWindow_Iconify   (cl,obj,(APTR)msg));
      case MUIM_MainWindow_About    : return(MainWindow_About     (cl,obj,(APTR)msg));
      case MUIM_MainWindow_AddURL   : return(MainWindow_AddURL    (cl,obj,(APTR)msg));
      case MUIM_MainWindow_BackURL  : return(MainWindow_BackURL   (cl,obj,(APTR)msg));
      case MUIM_MainWindow_ReloadURL: return(MainWindow_ReloadURL (cl,obj,(APTR)msg));
      case MUIM_MainWindow_Open     : return(MainWindow_Open      (cl,obj,(APTR)msg));
      case MUIM_MainWindow_Save     : return(MainWindow_Save      (cl,obj,(APTR)msg));
      case MUIM_MainWindow_Config   : return(MainWindow_Config    (cl,obj,(APTR)msg));
      case MUIM_MainWindow_Action   : return(MainWindow_Action    (cl,obj,(APTR)msg));
      case MUIM_MainWindow_Find     : return(MainWindow_Find      (cl,obj,(APTR)msg));
      case MUIM_MainWindow_Rexx     : return(MainWindow_Rexx      (cl,obj,(APTR)msg));
   }
   return(DoSuperMethodA(cl,obj,msg));
}

///

// ARexx

/// Rexx_URL
SAVEDS ASM LONG Rexx_URL (REG(a2) Object *app)
{
   set(app, MUIA_Application_RexxString,
      DoMethod(win, MUIM_MainWindow_Action, ACTION_geturl));
   return(0);
}
///
/// Rexx_Save
SAVEDS ASM LONG Rexx_Save (REG(a1) struct {char *name;} *msg)
{
   if(msg->name)
      DoMethod(win, MUIM_MainWindow_Save, msg->name);
   else
      DoMethod(win, MUIM_MainWindow_Save, 0);

   return(0);
}
///
/// Rexx_Open
SAVEDS ASM LONG Rexx_Open(REG(a1) struct {char *name;} *msg)
{
   if(msg->name)
      DoMethod(win, MUIM_MainWindow_Open, msg->name);
   else
      DoMethod(win, MUIM_MainWindow_Open, 0);

   return(0);
}
///
/// Rexx_Find
SAVEDS ASM LONG Rexx_Find (REG(a1) struct {char *str; LONG first; LONG next;} *msg)
{
   if(msg->str)
      DoMethod(win, MUIM_MainWindow_Find, FIND_word, msg->str);
   else if(msg->first)
      DoMethod(win, MUIM_MainWindow_Find, FIND_first, 0);
   else if(msg->next)
      DoMethod(win, MUIM_MainWindow_Find, FIND_next, 0);
   else
      DoMethod(win, MUIM_MainWindow_Find, FIND_new, 0);
   return(0);
}
///
/// Rexx_Print
SAVEDS ASM LONG Rexx_Print(REG(a1) Msg msg)
{
   DoMethod(win, MUIM_MainWindow_Action, ACTION_print);
   return(0);
}
///
/// Rexx_View
SAVEDS ASM LONG Rexx_View(REG(a1) Msg msg)
{
   DoMethod(win, MUIM_MainWindow_Action, ACTION_viewsrc);
   return(0);
}
///
/// Rexx_Reload
SAVEDS ASM LONG Rexx_Reload(REG(a1) Msg msg)
{
   DoMethod(win, MUIM_MainWindow_ReloadURL);
   return(0);
}
///
/// Rexx_Back
SAVEDS ASM LONG Rexx_Back(REG(a1) Msg msg)
{
   DoMethod(win, MUIM_MainWindow_BackURL);
   return(0);
}
///

// Init

/// ExitLibs
VOID ExitLibs(VOID)
{
   if (IntuitionBase) CloseLibrary(IntuitionBase);
   if (GfxBase      ) CloseLibrary(GfxBase      );
   if (AslBase      ) CloseLibrary(AslBase      );
   if (UtilityBase  ) CloseLibrary(UtilityBase  );
   if (MUIMasterBase) CloseLibrary(MUIMasterBase);
}
///
/// InitLibs
BOOL InitLibs(VOID)
{
   MUIMasterBase = OpenLibrary("muimaster.library",11);
   UtilityBase   = OpenLibrary("utility.library"  ,36);
   AslBase       = OpenLibrary("asl.library"      ,36);
   GfxBase       = OpenLibrary("graphics.library" ,36);
   IntuitionBase = OpenLibrary("intuition.library",36);

   if (MUIMasterBase && UtilityBase && AslBase && GfxBase && IntuitionBase)
      return(TRUE);

   ExitLibs();
   return(FALSE);
}
///
/// ExitClasses
VOID ExitClasses(VOID)
{
   if (CL_Dtpic       )    MUI_DeleteCustomClass(CL_Dtpic       );
   if (CL_MainWindow  )    MUI_DeleteCustomClass(CL_MainWindow  );
}
///
/// InitClasses
BOOL InitClasses(VOID)
{
   CL_MainWindow   = MUI_CreateCustomClass(NULL,MUIC_Window    ,NULL,sizeof(struct MainWindow_Data  )    ,MainWindow_Dispatcher  );
   CL_Dtpic        = MUI_CreateCustomClass(NULL,MUIC_Area      ,NULL,sizeof(struct DtpicData  )          ,DtpicDispatcher  );

   if (CL_MainWindow && CL_Dtpic)
      return(TRUE);

   ExitClasses();
   return(FALSE);
}
///
/// HandleArgs
const char CLITemplate[] = "URL";

const char CLIHelp[] =
   "\n"
   "\033[1mmoreHTML " VERS "\033[0m\n"
   "(C)opyright by Dirk Holtwick, 1997\n"
   "\n"
   "Usage: moreHTML <url>\n"
   " <url>   : filename or URL of the file to be displayed\n";

LONG HandleArgs(char *filename)
{
   struct RDArgs *rda,*rdas;
   LONG msg = 0;

   struct CLIArgs
   {
      char *url;
   } argarray = { 0 };

   if (rdas = AllocDosObject(DOS_RDARGS,NULL))
   {
      rdas->RDA_ExtHelp = (char *)CLIHelp;

      if (rda = ReadArgs((char *)CLITemplate,(LONG *)&argarray,rdas))
      {
         if (argarray.url)
         {
            strcpy(filename, argarray.url);
         }
         FreeArgs(rda);
      }
      FreeDosObject(DOS_RDARGS,rdas);
   }
   return(msg);
}
///

// Main

/// Main Program

int main(int argc,char *argv[])
{
   struct   WBStartup *wbmsg;
   ULONG    sigs=0, id;
   Object   *app;
   int      res;
   int      msg=0;
   char     filename[256];

   static const struct Hook Rexx_URLHook       = { { NULL,NULL },(VOID *)Rexx_URL     ,NULL,NULL };
   static const struct Hook Rexx_SaveHook      = { { NULL,NULL },(VOID *)Rexx_Save    ,NULL,NULL };
   static const struct Hook Rexx_OpenHook      = { { NULL,NULL },(VOID *)Rexx_Open    ,NULL,NULL };
   static const struct Hook Rexx_PrintHook     = { { NULL,NULL },(void *)Rexx_Print   ,NULL,NULL };
   static const struct Hook Rexx_BackHook      = { { NULL,NULL },(void *)Rexx_Back    ,NULL,NULL };
   static const struct Hook Rexx_ReloadHook    = { { NULL,NULL },(void *)Rexx_Reload  ,NULL,NULL };
   static const struct Hook Rexx_ViewHook      = { { NULL,NULL },(void *)Rexx_View    ,NULL,NULL };
   static const struct Hook Rexx_FindHook      = { { NULL,NULL },(void *)Rexx_Find    ,NULL,NULL };

   // ARexx commands
   static struct MUI_Command commands[] =
   {
      { "url"       ,""                    , 0        , (void *)&Rexx_URLHook     },
      { "save"      ,"file/k"              , 1        , (void *)&Rexx_SaveHook    },
      { "open"      ,"url=file/k"          , 1        , (void *)&Rexx_OpenHook    },
      { "find"      ,"string=word/k,first=top/s,next/s"
                                           , 3        , (void *)&Rexx_FindHook    },
      { "print"     ,""                    , 0        , (void *)&Rexx_PrintHook   },
      { "back"      ,""                    , 0        , (void *)&Rexx_BackHook    },
      { "reload"    ,""                    , 0        , (void *)&Rexx_ReloadHook  },
      { "view"      ,""                    , 0        , (void *)&Rexx_ViewHook    },
      { NULL        , NULL                 , NULL     , NULL                      }
   };

   DB("\n*** moreHTML ***\n");

   filename[0] = 0;

   // Starting from CLI
   if(argc!=0)
   {
      HandleArgs(filename);
   }
   // Starting from WB
   else
   {
      wbmsg = (struct WBStartup *)argv;

      if(wbmsg->sm_NumArgs>=2)
      {
         NameFromLock(wbmsg->sm_ArgList[1].wa_Lock,filename,255);
         AddPart(filename,wbmsg->sm_ArgList[1].wa_Name,255);
      }
   }

// InitLocale();

   if (InitLibs())
   {

      if (InitClasses())
      {

         app = ApplicationObject,
            MUIA_Application_Title      , NAME,
            MUIA_Application_Version    , "$VER: " NAME" " VERS " " __AMIGADATE__,
            MUIA_Application_Copyright  , "Copyright © Dirk Holtwick, 1997",
            MUIA_Application_Author     , "Dirk Holtwick",
            MUIA_Application_Description, "Simple HTML viewer based on HTMLtext.mcc",
            MUIA_Application_Base       , "MOREHTML",
//          MUIA_Application_SingleTask , TRUE,
            MUIA_Application_Commands   , commands,
            MUIA_Application_Window     , win  = NewObject(CL_MainWindow->mcc_Class,NULL,TAG_DONE),
            End;

         if (app)
         {
            // Get configuration
            DoMethod(win, MUIM_MainWindow_Config, TRUE);

            // Open window before a text is loaded,
            // otherwise the background is crippled
            set(win,MUIA_Window_Open,TRUE);

            // InitARexx
/*
            InitARexx(&adata,(char *)xget(app,MUIA_Application_Base));
*/
            if(filename[0]) DoMethod(win, MUIM_MainWindow_Open,filename);

            while ((id = DoMethod(app,MUIM_Application_NewInput,&sigs)) != MUIV_Application_ReturnID_Quit)
            {
               if (sigs)
               {
                  sigs = Wait(sigs | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F);

                  /* quit when receiving break from console */
                  if (sigs & SIGBREAKF_CTRL_C)
                     break;

                  /* deiconify & activate on ctrl-f just like the other prefs programs */
                  if (sigs & SIGBREAKF_CTRL_F)
                  {
                     set(app,MUIA_Application_Iconified,FALSE);
                     set(win,MUIA_Window_Open,TRUE);
                  }
               }
            }

            // FreeARexx
/*
            FreeARexx(&adata);
*/
            // Remove temporary rexx file
            remove(TMPREXX);

            set(win,MUIA_Window_Open,FALSE);
         }
         MUI_DisposeObject(app);
         ExitClasses();
      }
      ExitLibs();
   }

   if (msg)
   {
/*
      char *str = GetStr(msg);
      char *c = strchr(str,'(');
      Write(Output(),str,strlen(str));
      res = c ? atol(c+1) : RETURN_OK;
*/
      res = RETURN_OK;
   }
   else
      res = RETURN_OK;

//   ExitLocale();

   DB("*** finish ***\n");

   exit(res);
}
///

