/**************************************************************************/
/*                                                                        */
/* RexxMail installation program.                                         */
/*                                                                        */
/**************************************************************************/
/*                                                                        */
/* This program forms part of the RexxMail package, and may not be        */
/* distributed separately.                                                */
/*                                                                        */
/**************************************************************************/
/*                                                                        */
/* The latest version of RexxMail can be found at                         */
/*          www.degeus.com/rexxmail  */
/*                                                                        */
/**************************************************************************/
/*                                                                        */
/* This program is released under the terms of the GNU license, see       */
/*          www.gnu.org/copyleft/gpl.html                                 */
/*                                                                        */
/**************************************************************************/
/*                                                                        */
/* (c) GLOBAL.!THISYEAR Marcus de Geus  */
/*          marcus@degeus.com  */
/*          www.degeus.com  */
/*                                                                        */
/**************************************************************************/
/*                                                                        */
/* Use it if you like it. Don't if you don't. No legalese.                */
/*                                                                        */
/**************************************************************************/

/**************************************************************************/
/* Some general bits                                                      */
/**************************************************************************/

signal on Halt  /* handles halt condition */
signal on NoValue  /* handles initialization errors */
signal on Syntax  /* handles syntax errors */

/**************************************************************************/
/* Define the build number                                                */
/**************************************************************************/

Global.Build = 20061224.155329  /* define the build number */

/**************************************************************************/
/* Define the program directory                                           */
/**************************************************************************/

parse source OS . ProgSpec  /* get the program name */
ProgDrive = filespec('D',ProgSpec)  /* the program dir drive */
ProgDir = ProgDrive||strip(filespec('P',ProgSpec),'T','\')  /* the full program directory path */

/**************************************************************************/
/* Define the user folders location file                                  */
/**************************************************************************/

LocFile = ProgDir||'\location.txt'  /* the user location file */
NewInstall = (stream(LocFile,'C','QUERY EXISTS') = '')  /* if we have no location file, it is a new installation */

/**************************************************************************/
/* Start a log file                                                       */
/**************************************************************************/

Global.LogFile = ProgDir||'\install.log'  /* define the log file name */
call WriteLog date('S')||' '||time('N')||' : Installation started.'  /* report */

/**************************************************************************/
/* Make sure this is OS/2                                                 */
/**************************************************************************/

if (OS >< 'OS/2') then  /* if the OS is not OS/2 */
do
 call WriteLog '  ERROR: this program requires OS/2'  /* report */
 call Halt  /* and quit */
end

/**************************************************************************/
/* Check for the REXX utilities library                                   */
/**************************************************************************/

if (\LoadRexxUtils()) then  /* if we cannot use or load the Rexx utility functions */
do
 call WriteLog '  ERROR: Cannot load Rexx utility functions.'  /* report */
 call Halt  /* and quit */
end

/**************************************************************************/
/* Make sure we have the utilities level we need                          */
/**************************************************************************/

if (rxfuncquery('sysutilversion')) then  /* if we cannot find the SysUtilVersion function */
do
 RexxVersionOK = 0  /* all is not well */
end
else  /* if we can find the SysUtilVersion function */
do
 RexxVersionOK = (sysutilversion() >= '2.00')  /* if the utilities level is at least 2.00, all is well */
end

if (\RexxVersionOK) then  /* if we do not have the right REXX utilities version */
do
 call WriteLog '  ERROR: REXXUTIL.DLL is not at the required level'  /* report */
 call Halt  /* and quit */
end

/**************************************************************************/
/* See what the command line brings us                                    */
/**************************************************************************/

Global.CRLF = d2c(13)||d2c(10)  /* define CRLF */
Global.Auto = 0  /* no auto processing yet */
Global.CWMF = 0  /* no auto processing yet */
Global.Objects = 0  /* no auto processing yet */
UserName = ''  /* no user name yet */

parse arg Arguments  /* get any arguments */

do while (Arguments >< '')  /* go on while we have something */

 parse var Arguments NextArg Arguments  /* get the next argument */

 select  /* do one of the following */

  when (translate(NextArg) = '/AUTO') then  /* if it is this one */
  do
   Global.Auto = 1  /* we want automatic processing */
  end

  when (translate(NextArg) = '/CWMF') then  /* if it is this one */
  do
   Global.CWMF = 1  /* we want the CWMF class */
  end

  when (translate(NextArg) = '/OBJECTS') then  /* if it is this one */
  do
   Global.Objects = 1  /* we want to (re)create the program objects etc. */
  end

  when (left(NextArg,1) = '/') then  /* if it starts with a / */
  do
   call WriteLog '  ERROR: Invalid command-line switch "'||NextArg||'"'  /* report */
  end

  otherwise  /* if none of the above */
  do

   if (UserName >< '') then  /* if we already have a user name */
   do
    call WriteLog '  ERROR: User name must be a single word'  /* report */
    call Halt  /* and quit */
   end

   UserName = NextArg  /* use it */

  end

 end

end

/**************************************************************************/
/* Do some sanity checking                                                */
/**************************************************************************/

GotError = 0  /* no errors yet */

if (Global.Objects) then  /* if we want to (re)create objects */
do

 if (NewInstall) then  /* if this is a new installation attempt */
 do
  call WriteLog '  ERROR: /Objects cannot be used for a new installation'  /* report */
  GotError = 1  /* we have an error */
 end

 if (UserName >< '') then  /* if we have a user name */
 do
  call WriteLog '  ERROR: /Objects cannot be combined with a user name'  /* report */
  GotError = 1  /* we have an error */
 end

 if (Global.CWMF) then  /* if we also want CWMF mode */
 do
  call WriteLog '  ERROR: /Objects cannot be combined with /CWMF'  /* report */
  GotError = 1  /* we have an error */
 end

end

if (GotError) then  /* if we have one or more errors */
do
 call Halt  /* quit */
end

/**************************************************************************/
/* See if we want to (re)create the program objects etc.                  */
/**************************************************************************/

if (Global.Objects) then  /* if we want to */
do
 call InstallObjects  /* (re)create or update the program objects etc. */
 call Quit  /* and quit */
end

/**************************************************************************/
/* Get a user name from the environment if necessary                      */
/**************************************************************************/

if (UserName = '') then  /* if there is no user name */
do

 UserName = value('USER',,'OS2ENVIRONMENT')  /* look for a user name in the OS/2 environment */

 if (UserName = '') then  /* if no user name is found */
 do
  UserName = 'DEFAULT'  /* use the default value */
 end

end

/**************************************************************************/
/* Prompt for action                                                      */
/**************************************************************************/

call StartExplain  /* explain to the user what's going to happen */

if (\UserQuery('Continue?')) then  /* if the user gives a negative reply */
do
 call WriteLog '         Installation aborted by user.'  /* report */
 call Halt  /* quit */
end

/**************************************************************************/
/* See what the current update status looks like                          */
/**************************************************************************/

if (NewInstall) then  /* if we have a new installation */
do

 call WriteLog '         Creating new installation for build '||Global.Build||'.'  /* report */
 call InstallExplain  /* explain what's going to happen */

 if (UserQuery('Continue?')) then  /* if the user reply is positive */
 do

  if (\DoInstall(NewInstall)) then  /* if we cannot install the program */
  do
   call Halt  /* quit */
  end

 end
 else  /* if the user reply was negative */
 do
  call WriteLog '         Program installation refused by user.'  /* report */
 end

end
else  /* if it is not a new installation */
do

 if (stream(ProgDir||'\update\program\location.txt','C','QUERY EXISTS') = '') then  /* if we have already installed or updated the program */
 do
  Message = 'There are no program components to install or update.'  /* the text to report */
  call WriteLog '         '||Message  /* report */
  call UserPrompt Message  /* wait for the user */
 end
 else  /* if we still have an update to do */
 do

  call WriteLog '         Updating existing installation to build '||Global.Build||'.'  /* report */
  call InstallExplain  /* explain what's going to happen */
  call UpdateExplain  /* explain to the user */

  if (UserQuery('Continue?')) then  /* if the user reply is positive */
  do

   if (\DoInstall(NewInstall)) then  /* if we cannot install the program */
   do
    call Halt  /* quit */
   end

  end
  else  /* if the user reply was negative */
  do
   call WriteLog '         Program update refused by user.'  /* report */
  end

 end

end

if (stream(LocFile,'C','QUERY EXISTS') = '') then  /* if we have no location file */
do
 call WriteLog '  ERROR: Missing location file.'  /* report */
 call Halt  /* and quit */
end

if (\GotUser(LocFile,UserName)) then  /* if we do not find this user in the location file */
do

 call WriteLog '         User "'||UserName||'" is not in "'||LocFile||'"; installing new user.'  /* report */
 call UserInstallExplain  /* explain to the user */

 if (UserQuery('Install mail folders for user "'||UserName||'"?')) then  /* if the user reply is positive */
 do

  if (\InstallUser()) then  /* if we cannot install a new user */
  do
   call Halt  /* quit */
  end

 end
 else  /* if the user reply is negative */
 do
  call WriteLog '         New user installation refused by user.'  /* report */
 end

end
else  /* if we found this user in the location file */
do
 call WriteLog '         User "'||UserName||'" is in "'||LocFile||'"; no new user installation required.'  /* report */
end

if (Global.CWMF) then  /* if we want the CWMailFile class */
do

 if (sysregisterobjectclass('CWMailFile',ProgDir||'\cwmailfileclass\rexxmail.dll')) then  /* if we can register the class */
 do
  call WriteLog '         The CWMailFile class has been registered.'  /* report */
 end
 else  /* if we cannot register the class */
 do
  call WriteLog '  ERROR: Cannot register the CWMailFile class.'  /* report */
  return 0  /* quit with an error */
 end

end

call ClearScreen  /* clear the screen */
address cmd '@call '||ProgDir||'\rexxmail.cmd /setprogramobjecticons >> '||ProgDir||'\RexxMail.OUT'  /* set the program object icons */

call Quit  /* that's all, folks! */

/**************************************************************************/
DoInstall:  /* optionally (re)installs all the bits and pieces */
/**************************************************************************/

parse arg NewInstall  /* get the argument */

if (NewInstall) then  /* if this is a new installation */
do

 call WarningExplain  /* send out a warning if necessary */

 if (\UserQuery('Continue?')) then  /* if the user reply is negative */
 do
  return 0  /* quit with an error */
 end

end
else  /* if this is not a new installation */
do

 call sysfiledelete ProgDir||'\update\program\location.txt'  /* get rid of the location.txt template */

 if (sysdestroyobject(ProgDir||'\help')) then  /* if we can get rid of any remaining old help dir */
 do
  call WriteLog '         Removed obsolete Help folder from program directory.'  /* report */
 end

 if (sysdestroyobject('<REXXMAIL_HELP>')) then  /* if we can get rid of any remaining old help object */
 do
  call WriteLog '         Removed obsolete Help object.'  /* report */
 end

end

if (\InstallProgram()) then  /* if we have a negative result */
do
 return 0  /* quit with an error */
end

if (\InstallIcons()) then  /* if we cannot install the icons */
do
 return 0  /* quit with an error */
end

if (\InstallObjects()) then  /* if we cannot install the program objects */
do
 return 0  /* quit with an error */
end

call sysdestroyobject ProgDir||'\update\icons'  /* get rid of the icons update folder */
call sysdestroyobject ProgDir||'\update\program'  /* get rid of the program files update folder */

return 1  /* end of DoInstall */

/**************************************************************************/
InstallProgram:  /* (re)installs the program files */
/**************************************************************************/

if (\CheckDir(ProgDir||'\update\program')) then  /* if the program dir is not OK */
do
 return 0  /* return with an error */
end

address cmd '@copy '||ProgDir||'\update\program\* '||ProgDir||' > NUL'  /* copy the program files */

if (RC = 0) then  /* if no error occurred */
do
 call WriteLog '         Copied RexxMail program files to "'||ProgDir||'".'  /* report */
end
else  /* if we cannot copy the files */
do
 call WriteLog '         Cannot copy RexxMail program files to "'||ProgDir||'".'  /* report */
 return 0  /* return with no success */
end

call MakeFolder 'RxMlUtil',ProgDir  /* try to create a RxMlUtil folder in the program dir */
RxMlUtilDir = ProgDir||'\RxMlUtil'  /* the full spec of the RxMlUtil folder */
address cmd '@copy '||ProgDir||'\update\program\rxmlutil\* '||RxMlUtilDir||' > NUL'  /* copy the RxMLUtil files */

if (RC = 0) then  /* if no error occurred */
do
 call WriteLog '         Copied RxMlUtil source files to "'||RxMlUtilDir||'".'  /* report */
end
else  /* if we cannot copy the files */
do
 call WriteLog '         Cannot copy RxMlUtil source files to "'||RxMlUtilDir||'".'  /* report */
 return 0  /* return with no success */
end

DLLDir = GetDLLDir()  /* get the OS/2 DLL dir */

if (DLLDir >< '') then  /* if we have a DLL dir */
do

 call DLLExplain  /* explain why */

 if (UserQuery('Copy RxMlUtil.DLL to "'||DLLDir||'"?')) then  /* if we get permission */
 do

  address cmd '@copy '||ProgDir||'\update\program\rxmlutil\rxmlutil.dll '||DllDir||' > NUL'  /* copy the RxMLUtil.DLL file to it */

  if (RC = 0) then  /* if no error occurred */
  do
   call WriteLog '         Copied RxMlUtil.DLL to "'||DLLDir||'".'  /* report */
  end
  else  /* if we cannot copy the files */
  do
   call WriteLog '         Cannot copy RxMlUtil.DLL to "'||DLLDir||'".'  /* report */
   return 0  /* return with no success */
  end

 end
 else  /* if we do not get permission */
 do
  call WriteLog '         RxMlUtil.DLL not copied to "'||DLLDir||'"; user will copy manually.'  /* report */
 end

end
else  /* if we have no DLL dir */
do
 call WriteLog 'The "OS2\DLL" directory could not be found on the boot drive. RxMlUtil.DLL could not be copied.'  /* report */
 call NoDLLExplain  /* explain */
 call UserPrompt ''  /* wait for the user */
end

GotCWMFC = 0  /* we have no CWMailFile class yet */
call sysqueryclasslist('ClassList.')  /* get the class list */

do Index = 1 to ClassList.0  /* look at each entry */

 if (word(ClassList.Index,1) = 'CWMailFile') then  /* if it is what we want */
 do
  call WriteLog '         (The CWMailFileClass is already registered.)'  /* report */
  GotCWMFC = 1  /* we have a CWMailFile class */
 end

end

if (\GotCWMFC) then  /* if the CWMailFile class is not already registered */
do

 if (MakeFolder('CWMailFileClass',ProgDir)) then  /* if we can create a CWMailFileClass folder in the program dir */
 do

  CWMFDir = ProgDir||'\CWMailFileClass'  /* the full dir spec */
  address cmd '@copy '||ProgDir||'\update\program\cwmailfileclass\* '||CWMFDir||' > NUL'  /* copy the CWMailFile class files */

  if (RC = 0) then  /* if no error occurred */
  do
   call WriteLog '         Copied CWMailFile class files to "'||CWMFDir||'".'  /* report */
  end
  else  /* if we cannot copy the files */
  do
   call WriteLog '         Cannot copy CWMailFile class files to "'||CWMFDir||'".'  /* report */
   return 0  /* return with no success */
  end

  if (MakeFolder('Sources',CWMFDir)) then  /* if we can create a Sources folder in the CWMailFileClass dir */
  do

   address cmd '@copy '||ProgDir||'\update\program\cwmailfileclass\sources\* '||CWMFDir||'\sources > NUL'  /* copy the source files */

   if (RC = 0) then  /* if no error occurred */
   do
    call WriteLog '         Copied CWMailFile source files to "'||CWMFDir||'\Sources".'  /* report */
   end
   else  /* if we cannot copy the files */
   do
    call WriteLog '         Cannot copy CWMailFile source files to "'||CWMFDir||'\Sources".'  /* report */
    return 0  /* return with no success */
   end

  end

 end

 if (\Global.Auto & \Global.CWMF) then  /* if we did not already ask for the CWMF class, and we are not in auto mode */
 do
  call CWMailFileExplain  /* explain what's going to happen */
  Global.CWMF = (UserQuery('Register the CWMailFile class?'))  /* see if we want it */
 end

end

return 1  /* end of InstallProgram */

/**************************************************************************/
InstallIcons:  /* installs the icons and background bitmap */
/**************************************************************************/

if (\CheckDir(ProgDir||'\update\icons')) then  /* if the icons dir does not check out OK */
do
 return 0  /* return with an error */
end

call sysdestroyobject ProgDir||'\icons'  /* get rid of any old icons dir */

if (\sysmoveobject(ProgDir||'\update\icons',ProgDir)) then  /* if we cannot move the icons folder to the prog dir */
do
 call WriteLog '  ERROR: Cannot move new icons folder to "'||Progdir||'".'  /* report */
 return 0  /* return with an error */
end

call WriteLog '         Moved new icons folder to "'||ProgDir||'".'  /* report */

return 1  /* end of InstallIcons */

/**************************************************************************/
InstallObjects:  /* installs the program objects */
/**************************************************************************/

/**************************************************************************/
/* Note order of calling MakeObject to make sure the program/file         */
/* associations are created in the correct order of menu preference.      */
/**************************************************************************/

Location = ProgDir||'\Objects'  /* the objects will be created in the Objects subdir of the program dir */

if (\MakeDir(Location)) then  /* if we cannot make the dir if necessary */
do
 return 0  /* return with an error */
end

ExeName = ProgDir||'\rexxmail.cmd'  /* the following objects use rexxmail.cmd in the program directory */

Settings = 'MINIMIZED=YES;'||,  /* start the following programs minimized */
           'NOAUTOCLOSE=NO;'||,  /* close the program session after completion */
           'PROGTYPE=WINDOWABLEVIO;'||,  /* use a VIO (OS/2) window */
           'STARTUPDIR='||ProgDir||';'  /* start the program in the RexxMail program directory */

AssocType = 'Mail Message In,Mail Message Sent'  /* the associations to use for the next few objects */

Title = 'View Message'  /* the title to use */
ObjectID = '<REXXMAIL_VIEW>'  /* the object id to use */
Parameters = '/View'  /* the RexxMail switch to use */

call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'View Raw Message'  /* the title to use */
ObjectID = '<REXXMAIL_VIEWRAW>'  /* the object id to use */
Parameters = '/ViewRaw'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

AssocType = 'Mail Message In'  /* the association to use for the next few objects */

Title = 'Forward'  /* the title to use */
ObjectID = '<REXXMAIL_FORWARD>'  /* the object id to use */
Parameters = '/Forward'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Forward and Open'  /* the title to use */
ObjectID = '<REXXMAIL_FORWARDOPEN>'  /* the object id to use */
Parameters = '/ForwardOpen'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reply'  /* the title to use */
ObjectID = '<REXXMAIL_REPLY>'  /* the object id to use */
Parameters = '/Reply'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reply and Open'  /* the title to use */
ObjectID = '<REXXMAIL_REPLYOPEN>'  /* the object id to use */
Parameters = '/ReplyOpen'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reply to All'  /* the title to use */
ObjectID = '<REXXMAIL_REPLYTOALL>'  /* the object id to use */
Parameters = '/ReplyToAll'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reply to All and Open'  /* the title to use */
ObjectID = '<REXXMAIL_REPLYTOALLOPEN>'  /* the object id to use */
Parameters = '/ReplyToAllOpen'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reply to All As List'  /* the title to use */
ObjectID = '<REXXMAIL_REPLYTOALLASLIST>'  /* the object id to use */
Parameters = '/ReplyToAllAsList'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reply to All As List and Open'  /* the title to use */
ObjectID = '<REXXMAIL_REPLYTOALLASLISTOPEN>'  /* the object id to use */
Parameters = '/ReplyToAllAsListOpen'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reply to List'  /* the title to use */
ObjectID = '<REXXMAIL_REPLYTOLIST>'  /* the object id to use */
Parameters = '/ReplyToList'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reply to List and Open'  /* the title to use */
ObjectID = '<REXXMAIL_REPLYTOLISTOPEN>'  /* the object id to use */
Parameters = '/ReplyToListOpen'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reply to Recipients'  /* the title to use */
ObjectID = '<REXXMAIL_REPLYTORECIPIENTS>'  /* the object id to use */
Parameters = '/ReplyToRecipients'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reply to Recipients and Open'  /* the title to use */
ObjectID = '<REXXMAIL_REPLYTORECIPIENTSOPEN>'  /* the object id to use */
Parameters = '/ReplyToRecipientsOpen'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reply to RecipientsAsList'  /* the title to use */
ObjectID = '<REXXMAIL_REPLYTORECIPIENTSASLIST>'  /* the object id to use */
Parameters = '/ReplyToRecipientsAsList'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reply to Recipients As List and Open'  /* the title to use */
ObjectID = '<REXXMAIL_REPLYTORECIPIENTSASLISTOPEN>'  /* the object id to use */
Parameters = '/ReplyToRecipientsAsListOpen'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

AssocType = 'Mail Message Out'  /* the association to use for the next few objects */

Title = 'Edit Message'  /* the title to use */
ObjectID = '<REXXMAIL_EDIT>'  /* the object id to use */
Parameters = '/Edit'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'ASCII/Quoted-Printable'  /* the title to use */
ObjectID = '<REXXMAIL_SETASCIIQP>'  /* the object id to use */
Parameters = '/SetASCIIQP'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'OK/Not OK to Send'  /* the title to use */
ObjectID = '<REXXMAIL_SETOKNOTOKTOSEND>'  /* the object id to use */
Parameters = '/SetOKnotOKtoSend'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

AssocType = 'Mail Message Sent'  /* the association to use for the next few objects */

Title = 'Resend'  /* the title to use */
ObjectID = '<REXXMAIL_RESEND>'  /* the object id to use */
Parameters = '/Resend'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

AssocType = 'Mail Message In,Mail Message Out,Mail Message Sent'  /* the associations to use for the next few objects */

Title = 'Add Addresses to All Open Messages'  /* the title to use */
ObjectID = '<REXXMAIL_ADDADDRESSESTOOPEN>'  /* the object id to use */
Parameters = '/AddAddressesToOpen'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Open Attachments Folder'  /* the title to use */
ObjectID = '<REXXMAIL_OPENATTACH>'  /* the object id to use */
Parameters = '/OpenAttach'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Close Attachments Folder'  /* the title to use */
ObjectID = '<REXXMAIL_CLOSEATTACH>'  /* the object id to use */
Parameters = '/CloseAttach'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Import Addresses'  /* the title to use */
ObjectID = '<REXXMAIL_ADDRESSIMPORT>'  /* the object id to use */
Parameters = '/AddressImport'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

AssocType = ''  /* no associations for the next few objects */

Title = 'Export Addresses'  /* the title to use */
ObjectID = '<REXXMAIL_ADDRESSEXPORT>'  /* the object id to use */
Parameters = '/AddressExport'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Open Mail Folders'  /* the title to use */
ObjectID = '<REXXMAIL_OPEN>'  /* the object id to use */
Parameters = '/Open %'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Close Mail Folders'  /* the title to use */
ObjectID = '<REXXMAIL_CLOSE>'  /* the object id to use */
Parameters = '/Close %'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Attach to All Messages in Out Folder'  /* the title to use */
ObjectID = '<REXXMAIL_ATTACHTOALLINOUT>'  /* the object id to use */
Parameters = '/AttachToAllInOut'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Attach to Open Message Folders'  /* the title to use */
ObjectID = '<REXXMAIL_ATTACHTOOPEN>'  /* the object id to use */
Parameters = '/AttachToOpen'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Reference Guide'  /* the title to use */
ObjectID = '<REXXMAIL_REFERENCE>'  /* the object id to use */
Parameters = '/Reference'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Tutorial'  /* the title to use */
ObjectID = '<REXXMAIL_TUTORIAL>'  /* the object id to use */
Parameters = '/Tutorial'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Settings = 'MINIMIZED=NO;'||,  /* start the program visible */
           'NOAUTOCLOSE=NO;'||,  /* close the program session after completion */
           'PROGTYPE=WINDOWABLEVIO;'||,  /* use a VIO (OS/2) window */
           'STARTUPDIR='||ProgDir||';'  /* start the program in the RexxMail program directory */

Title = 'Collect & Send Mail'  /* the title to use */
ObjectID = '<REXXMAIL_COLLECT_SENDREADY>'  /* the object id to use */
Parameters = '/Collect /Sendready'  /* the RexxMail switches to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Collect Mail'  /* the title to use */
ObjectID = '<REXXMAIL_COLLECT>'  /* the object id to use */
Parameters = '/Collect %'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Collect Interactively'  /* the title to use */
ObjectID = '<REXXMAIL_COLLECT_POP3INTERACTIVE>'  /* the object id to use */
Parameters = '/Collect /POP3Interactive %'  /* the RexxMail switches to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

Title = 'Send Ready Messages in Out Folder'  /* the title to use */
ObjectID = '<REXXMAIL_SENDREADY>'  /* the object id to use */
Parameters = '/Sendready %'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

AssocType = 'Mail Message Out'  /* the association to use for the next object */

Title = 'Send'  /* the title to use */
ObjectID = '<REXXMAIL_SEND>'  /* the object id to use */
Parameters = '/Send'  /* the RexxMail switch to use */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

AssocType = ''  /* no associations for the next objects */

ExeName = ProgDir||'\foldutil.cmd'  /* the following object uses foldutil.cmd in the program directory */

call syssetobjectdata '<REXXMAIL_USER_FOLDERS_UTILITY>','OBJECTID=<REXXMAIL_UTILITY>'  /* change any old-style utility ID */

Title = 'Utility'  /* the title to use */
ObjectID = '<REXXMAIL_UTILITY>'  /* the object id to use */
Parameters = ''  /* no parameters */
call MakeObject Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* make the object */

/**************************************************************************/
/* Install a CWMailFile class folder                                      */
/**************************************************************************/

Settings = 'ALWAYSSORT=YES;'||,  /* keep the folder sorted */
           'DEFAULTVIEW=DETAILS;'||,  /* the default view of the main directory is details */
           'DETAILSCLASS=CWMailFile;'||,  /* use the CWMailFile details class if possible */
           'SORTCLASS=CWMailFile;'||,  /* use the CWMailFile sorting class if possible */
           'OBJECTID=<REXXMAIL_FOLDER>;'||,  /* the object ID */
           'TEMPLATE=YES;'  /* make it a template object */

call MakeFolder 'Mail Folder',Location,Settings  /* try to make the Mail Folder template */

return 1  /* end of InstallObjects */

/**************************************************************************/
InstallUser:  /* Install a new user */
/**************************************************************************/

if (Global.Auto) then  /* if we want an automatic installation */
do
 MailLoc = ProgDrive||'\Mail_'||UserName  /* use this */
 call sysmkdir MailLoc  /* create the dir if necessary */
end
else  /* if we want manual mode */
do

 MailLoc = GetLoc(ProgDir)  /* get the location for the main Rexxmail mail folder */

 if (MailLoc = '*') then  /* if we have no location value */
 do
  call WriteLog '         User refused creation of main folder'  /* report */
  return 1  /* quit with no error */
 end

end

Settings = 'ALWAYSSORT=YES;'||,  /* keep the main directory sorted */
           'CCVIEW=NO;'||,  /* resurface existing folder view */
           'WORKAREA=YES;'||,  /* make the main directory a work area */
           'DEFAULTVIEW=ICON;'||,  /* the default view of the main directory is icons */
           'ICONVIEW=NORMAL,NONGRID;'||,  /* use standard view for these folders */
           'NORENAME=YES;'||,  /* the next folders cannot be renamed */
           'NOTVISIBLE=NO;'||,  /* the next folders are visible (in the main folder) */
           'DEFAULTSORT=-2;'  /* sort the next folder's contents by name */

if (\syssetobjectdata(MailLoc,Settings)) then  /* if we cannot change the main location settings */
do
 call WriteLog '  ERROR: Cannot change settings of directory "'||MailLoc||'".'  /* report */
end

if (\CheckDir(ProgDir||'\update\configuration')) then  /* if the original files dir is not OK */
do
 return 0  /* return with an error */
end

if (\CheckDir(ProgDir||'\update\configuration\lists')) then  /* if the original files dir is not OK */
do
 return 0  /* return with an error */
end

Settings = 'ALWAYSSORT=YES;'||,  /* always sort the next folder */
           'CCVIEW=NO;'||,  /* resurface existing folder view */
           'WORKAREA=NO;'||,  /* do not make the next folder a work area */
           'DEFAULTVIEW=ICON;'||,  /* use icon views for the next folder */
           'ICONVIEW=NORMAL,FLOWED;'||,  /* use flowed (multi-column) view for the folder */
           'NORENAME=YES;'||,  /* the next folder cannot be renamed */
           'NOTVISIBLE=NO;'||,  /* the next folder is visible in the main folder */
           'ICONFILE='||ProgDir||'\icons\folders\configuration_0.ico;'||,  /* the closed icon file */
           'ICONNFILE=1,'||ProgDir||'\icons\folders\configuration_1.ico;'||,  /* the open icon file */
           'DEFAULTSORT=-2;'  /* sort the next folder's contents by name */

if (\MakeFolder('Configuration',MailLoc,Settings)) then  /* if we cannot make the Configuration folder */
do
 return 0  /* return with an error */
end

Settings = 'ALWAYSSORT=YES;'||,  /* always sort the next folders */
           'CCVIEW=NO;'||,  /* resurface existing folder view */
           'WORKAREA=YES;'||,  /* make the next folders work areas */
           'DEFAULTVIEW=ICON;'||,  /* use icon views for the next folders */
           'ICONVIEW=NORMAL,FLOWED;'||,  /* use flowed (multi-column) view for the folders */
           'NORENAME=YES;'||,  /* the next folders cannot be renamed */
           'NOTVISIBLE=NO;'||,  /* the next folders are visible (in the main folder) */
           'ICONFILE='||ProgDir||'\icons\folders\addresses_0.ico;'||,  /* the closed icon file */
           'ICONNFILE=1,'||ProgDir||'\icons\folders\addresses_1.ico;'||,  /* the open icon file */
           'DEFAULTSORT=-2;'  /* sort the next folders' contents by name */

if (\MakeFolder('Addresses',MailLoc,Settings)) then  /* if we cannot make the Addresses folder */
do
 return 0  /* return with an error */
end

Settings = 'ALWAYSSORT=YES;'||,  /* always sort the next folders */
           'CCVIEW=NO;'||,  /* resurface existing folder view */
           'WORKAREA=YES;'||,  /* make the next folders work areas */
           'DEFAULTVIEW=ICON;'||,  /* use icon views for the next folders */
           'ICONVIEW=NORMAL,FLOWED;'||,  /* use flowed (multi-column) view for the folders */
           'NORENAME=YES;'||,  /* the next folders cannot be renamed */
           'NOTVISIBLE=NO;'||,  /* the next folders are visible (in the main folder) */
           'ICONFILE='||ProgDir||'\icons\folders\in_0.ico;'||,  /* the closed icon file */
           'ICONNFILE=1,'||ProgDir||'\icons\folders\in_1.ico;'||,  /* the open icon file */
           'DEFAULTSORT=-2;'  /* sort the next folders' contents by name */

if (\MakeFolder('In',MailLoc,Settings)) then  /* if we cannot make the In folder, no special icon */
do
 return 0  /* return with an error */
end

Settings = 'ALWAYSSORT=YES;'||,  /* always sort the next folders */
           'CCVIEW=NO;'||,  /* resurface existing folder view */
           'WORKAREA=YES;'||,  /* make the next folders work areas */
           'DEFAULTVIEW=ICON;'||,  /* use icon views for the next folders */
           'ICONVIEW=NORMAL,FLOWED;'||,  /* use flowed (multi-column) view for the folders */
           'NORENAME=YES;'||,  /* the next folders cannot be renamed */
           'NOTVISIBLE=NO;'||,  /* the next folders are visible (in the main folder) */
           'ICONFILE='||ProgDir||'\icons\folders\in_archive_0.ico;'||,  /* the closed icon file */
           'ICONNFILE=1,'||ProgDir||'\icons\folders\in_archive_1.ico;'||,  /* the open icon file */
           'DEFAULTSORT=-2;'  /* sort the next folders' contents by name */

if (\MakeFolder('In Archive',MailLoc,Settings)) then  /* if we cannot make the In Archive folder, no special icon */
do
 return 0  /* return with an error */
end

Settings = 'ALWAYSSORT=YES;'||,  /* always sort the next folders */
           'CCVIEW=NO;'||,  /* resurface existing folder view */
           'WORKAREA=YES;'||,  /* make the next folders work areas */
           'DEFAULTVIEW=ICON;'||,  /* use icon views for the next folders */
           'ICONVIEW=NORMAL,FLOWED;'||,  /* use flowed (multi-column) view for the folders */
           'NORENAME=YES;'||,  /* the next folders cannot be renamed */
           'NOTVISIBLE=NO;'||,  /* the next folders are visible (in the main folder) */
           'ICONFILE='||ProgDir||'\icons\folders\out_0.ico;'||,  /* the closed icon file */
           'ICONNFILE=1,'||ProgDir||'\icons\folders\out_1.ico;'||,  /* the open icon file */
           'DEFAULTSORT=-2;'  /* sort the next folders' contents by name */

if (\MakeFolder('Out',MailLoc,Settings)) then  /* if we cannot make the Out folder, no special icon */
do
 return 0  /* return with an error */
end

Settings = 'ALWAYSSORT=YES;'||,  /* always sort the next folders */
           'CCVIEW=NO;'||,  /* resurface existing folder view */
           'WORKAREA=YES;'||,  /* make the next folders work areas */
           'DEFAULTVIEW=ICON;'||,  /* use icon views for the next folders */
           'ICONVIEW=NORMAL,FLOWED;'||,  /* use flowed (multi-column) view for the folders */
           'NORENAME=YES;'||,  /* the next folders cannot be renamed */
           'NOTVISIBLE=NO;'||,  /* the next folders are visible (in the main folder) */
           'ICONFILE='||ProgDir||'\icons\folders\out_archive_0.ico;'||,  /* the closed icon file */
           'ICONNFILE=1,'||ProgDir||'\icons\folders\out_archive_1.ico;'||,  /* the open icon file */
           'DEFAULTSORT=-2;'  /* sort the next folders' contents by name */

if (\MakeFolder('Out Archive',MailLoc,Settings)) then  /* if we cannot make the Out Archive folder, no special icon */
do
 return 0  /* return with an error */
end

Settings = 'ALWAYSSORT=YES;'||,  /* always sort the next folders */
           'CCVIEW=NO;'||,  /* resurface existing folder view */
           'WORKAREA=YES;'||,  /* make the next folders work areas */
           'DEFAULTVIEW=ICON;'||,  /* use icon views for the next folders */
           'ICONVIEW=NORMAL,FLOWED;'||,  /* use flowed (multi-column) view for the folders */
           'NORENAME=YES;'||,  /* the next folders cannot be renamed */
           'NOTVISIBLE=NO;'||,  /* the next folders are visible (in the main folder) */
           'ICONFILE='||ProgDir||'\icons\folders\lists_0.ico;'||,  /* the closed icon file */
           'ICONNFILE=1,'||ProgDir||'\icons\folders\lists_1.ico;'||,  /* the open icon file */
           'DEFAULTSORT=-2;'  /* sort the next folders' contents by name */

if (\MakeFolder('Lists',MailLoc||'\Configuration',Settings)) then  /* if we cannot make the Lists folder */
do
 return 0  /* return with an error */
end

Settings = 'ALWAYSSORT=YES;'||,  /* always sort the next folders */
           'CCVIEW=NO;'||,  /* resurface existing folder view */
           'WORKAREA=YES;'||,  /* make the next folders work areas */
           'DEFAULTVIEW=ICON;'||,  /* use icon views for the next folders */
           'ICONVIEW=NORMAL,FLOWED;'||,  /* use flowed (multi-column) view for the folders */
           'NORENAME=NO;'||,  /* the next folders can be renamed */
           'NOTVISIBLE=NO;'||,  /* the next folders are visible */
           'DEFAULTSORT=-2;'  /* sort the next folders' contents by name */

if (\MakeFolder('Read',MailLoc||'\In Archive',Settings)) then  /* if we cannot make the Read folder */
do
 return 0  /* return with an error */
end

if (\MakeFolder('Sent',MailLoc||'\Out Archive',Settings)) then  /* if we cannot make the Sent folder */
do
 return 0  /* return with an error */
end

if (\MakeFolder('RexxMail',MailLoc||'\In Archive',Settings)) then  /* if we cannot make the incoming RexxMail folder */
do
 return 0  /* return with an error */
end

if (\MakeFolder('RexxMail',MailLoc||'\Out Archive',Settings)) then  /* if we cannot make the outgoing RexxMail folder */
do
 return 0  /* return with an error */
end

UpdateFile = ProgDir||'\settupda.txt'  /* the name of the settings update template file */
SettingsFile = MailLoc||'\configuration\settings.txt'  /* the name of the new user settings file */

if (stream(UpdateFile,'C','OPEN READ') >< 'READY:') then  /* if we cannot open the settings update template file */
do
 call WriteLog '  ERROR: Cannot open settings template file "'||UpdateFile||'".'  /* report */
 return 0  /* return with an error */
end

if (stream(SettingsFile,'C','OPEN') >< 'READY:') then  /* if we cannot open the new settings file */
do
 call WriteLog '  ERROR: Cannot open user settings file "'||SettingsFile||'".'  /* report */
 return 0  /* return with an error */
end

WatchNext = 0  /* nothing doing yet */

do while (lines(UpdateFile))  /* as long as we have lines left in the update template file */

 InLine = linein(UpdateFile)  /* get the next line */

 if (WatchNext) then  /* if we have to watch this one */
 do

  if (pos(' = ',InLine) > 0) then  /* if it is a parameter line */
  do
   Inline = subword(InLine,2)  /* get rid of the first word (the comment "#") */
  end

 end

 WatchNext = (InLine = copies('#',72))  /* if the line is a separator, watch the next one */
 call lineout SettingsFile,InLine  /* write the result to the new settings file */

end

call stream UpdateFile,'C','CLOSE'  /* close the template file */
call stream SettingsFile,'C','CLOSE'  /* close the settings file */
call sysfiletree ProgDir||'\update\configuration\*','Files.','FO'  /* look for files in the original files source directory */

do Index = 1 to Files.0  /* take each of the files we found */

 if (syscopyobject(Files.Index,MailLoc||'\Configuration')) then  /* if we can copy it to the Configuration folder */
 do
  call WriteLog '         Copied file "'||Files.Index||'" to "'||MailLoc||'\Configuration".'  /* report */
 end
 else  /* if we cannot copy the file to the Configuration folder */
 do
  call WriteLog '         Cannot copy "'||Files.Index||'" to "'||MailLoc||'\Configuration".'  /* report */
 end

end

ListFile = ProgDir||'\update\configuration\lists\maillist'  /* the mailing list sample file */

if (syscopyobject(ListFile,MailLoc||'\Configuration\Lists')) then  /* if we can copy the maillist sample to the Lists folder */
do
 call WriteLog '         Copied file "'||ListFile||'" to "'||MailLoc||'\Configuration\Lists".'  /* report */
end
else  /* if we cannot copy the file to the Lists folder */
do
 call WriteLog '         Cannot copy "'||ListFile||'" to "'||MailLoc||'\Configuration\Lists".'  /* report */
end

if (stream(LocFile,'C','OPEN WRITE') >< 'READY:') then  /* if we cannot open the location file */
do
 call WriteLog '  ERROR: Cannot write main mail folder location "'||MailLoc||'" to "'||LocFile||'".'  /* report */
 return 0  /* return with an error */
end

call lineout LocFile,d2c(13)||d2c(10)||UserName||' = 'MailLoc  /* write the location and user name to the location file, starting on a new line */
call stream LocFile,'C','CLOSE'  /* close the file */
call WriteLog '         Main mail folder location "'||MailLoc||'" written to "'||LocFile||'".'  /* report */

if (\MakeShadow('<REXXMAIL_OPEN>','<WP_DESKTOP>')) then  /* if we cannot make a shadow of the Open program object on the desktop */
do
 return 0  /* return with an error */
end

GotError = 0  /* no errors yet */
call value 'USER',UserName,'OS2ENVIRONMENT'  /* set the user name in the OS/2 environment */

if (RC = 0) then  /* if all went well */
do
 call WriteLog '         Program object icons set.'  /* report */
end
else  /* if an error occurred */
do
 GotError = 1  /* we have an error */
 call WriteLog '  ERROR: Cannot set program object icons; see RexxMail.OUT for more info.'  /* report */
end

call ClearScreen  /* clear the screen */
address cmd '@call '||ProgDir||'\rexxmail.cmd /addressimport='||ProgDir||'\update\configuration\addresses.txt >> '||ProgDir||'\RexxMail.OUT'  /* import the default addresses */

if (RC = 0) then  /* if all went well */
do
 call WriteLog '         Created sample message templates in "'||MailLoc||'\Addresses".'  /* report */
end
else  /* if an error occurred */
do
 GotError = 1  /* we have an error */
 call WriteLog '  ERROR: Cannot create message templates in "'||MailLoc||'\Addresses"; see RexxMail.OUT for more info.'  /* report */
end

call ClearScreen  /* clear the screen */
address cmd '@call '||ProgDir||'\rexxmail.cmd /toolbarcreate >> '||ProgDir||'\RexxMail.OUT'  /* create the default toolbar if it does not exist */

if (RC = 0) then  /* if all went well */
do
 call WriteLog '         Created default toolbar.'  /* report */
end
else  /* if an error occurred */
do
 GotError = 1  /* we have an error */
 call WriteLog '  ERROR: Cannot create default toolbar; see RexxMail.OUT for more info.'  /* report */
end

if (\GotError) then  /* if no errors occurred */
do
 call sysfiledelete ProgDir||'\RexxMail.OUT'  /* get rid of the output file */
end

Message = 'The following combination has been added to "location.txt" :'||Global.CRLF||Global.CRLF||,  /* report */
          '  User name   : "'||UserName||'"'||Global.CRLF||,  /* report */
          '  Main folder : "'||MailLoc||'"'  /* report */
call UserPrompt Message  /* wait for the user if necessary */

return 1  /* end of InstallUser */

/**************************************************************************/
GetLoc: procedure expose Global.  /* get a location for the main folder */
/**************************************************************************/

parse upper arg ProgDir  /* get the argument in upper case */

do until (Location >< '')  /* go on until we can leave */

 call ClearScreen  /* clear the screen */
 call lineout 'CON:','Please enter the full drive, path and name for the user mail directory,'  /* show a message */
 call lineout 'CON:','which must NOT be in the RexxMail program directory or vice versa:'  /* show a message */
 call lineout 'CON:',''  /* empty line */
 parse pull Location  /* get a location from the user */

 if (Location >< '') then  /* if we have something */
 do

  Location = strip(Location,'B',' ')  /* remove excess spaces */
  Location = strip(Location,'B','\')  /* remove any trailing backslash */

  DriveBit = filespec('D',Location)  /* get the drive bit */

  if (DriveBit = '') then  /* if we have no drive bit */
  do
   Location = ''  /* try again */
  end
  else  /* if we do have a drive bit */
  do

   PathBit = filespec('P',Location)||filespec('N',Location)  /* get the path bit (and any name bit) */

   if (PathBit = '') then  /* if we have no path bit */
   do
    Location = ''  /* try again */
   end

   if (pos(ProgDir,translate(Location)) > 0) then  /* if the location is somewhere in the program dir */
   do
    Location = ''  /* try again */
   end

   if (pos(translate(Location),ProgDir) > 0) then  /* if the program dir is somewhere in the location */
   do
    Location = ''  /* try again */
   end

  end

  if (Location >< '') then  /* if we still have something */
  do

   call sysfiletree Location,'Dir.','DO'  /* see if the dir exists */

   if (Dir.0 = 1) then  /* if it does */
   do

    Location = Dir.1  /* use it */
    call sysfiletree Location||'\*.*','Stuff.','BO'  /* look for files and directories in the location */

    if (Stuff.0 > 0) then  /* if we found anything */
    do

     call lineout 'CON:',''  /* empty line */
     call lineout 'CON:','"'||Location||'" is not empty;'  /* report */
     call lineout 'CON:',''  /* empty line */

     if (\UserQuery('Use the directory anyway?')) then  /* if the reply is negative */
     do
      Location = ''  /* try again */
     end

    end

   end
   else  /* if the location does not exist */
   do

    call lineout 'CON:',''  /* empty line */
    call lineout 'CON:','"'||Location||'" does not exist;'  /* report */
    call lineout 'CON:',''  /* empty line */

    if (\UserQuery('Create a new directory?')) then  /* if the reply is negative */
    do
     Location = ''  /* try again */
    end
    else  /* if we can go ahead */
    do

     NextPos = 3  /* start looking at position 3 (well, actually 4, since we add 1 later) */

     do until (NextPos = 0)  /* go on until we reach the end of the line */

      NextPos = pos('\',Location,(NextPos + 1))  /* get the next backslash position */

      if (NextPos = 0) then  /* if we have reached the end of the line */
      do
       NextDir = Location  /* we have the whole dir spec */
      end
      else  /* if not */
      do
       NextDir = left(Location,(NextPos - 1))  /* get the next dir level */
      end

      call sysfiletree NextDir,'NextDir.','DO'  /* see if the dir exists */

      if (NextDir.0 = 0) then  /* if it does not */
      do

       if (sysmkdir(NextDir) = 0) then  /* if we can create the dir */
       do
        call WriteLog '         Created directory "'||NextDir||'".'  /* report */
       end
       else  /* if not */
       do
        call WriteLog 'ERROR:   Cannot create directory "'||NextDir||'".'  /* report */
        return '*'  /* make sure we quit */
       end

      end

     end

    end

   end

  end

 end

 if (Location = '') then  /* if we have no location, we can try again */
 do

  if (\UserQuery('You have not given a valid location. Try again?')) then  /* if the reply is negative */
  do
   return '*'  /* make sure we quit */
  end

 end

end

return Location  /* end of GetLoc */

/**************************************************************************/
GetDLLDir: procedure expose Global.  /* get the location of the OS/2 DLL dir if possible */
/**************************************************************************/

Location = ''  /* nothing yet */
ConfigFile = sysbootdrive()||'\config.sys'  /* the current config.sys file */

if (stream(ConfigFile,'C','OPEN READ') >< 'READY:') then  /* if we cannot open it for reading */
do
 call WriteLog 'ERROR:   Cannot open file "'||ConfigFile||'".'  /* report */
 return ''  /* return with nothing */
end

do while (lines(ConfigFile) & (Location = ''))  /* as long as we have lines left and did not get what we want */

 NextLine = linein(ConfigFile)  /* get the next line */

 if (left(translate(NextLine),8) = 'LIBPATH=') then  /* if we got the one we want */
 do

  parse var NextLine . '=' LibPath  /* get the full libpath */

  do until ((LibPath = '') | (Location >< ''))  /* run through the libpath until we get what we want */

   parse var LibPath NextPath ';' LibPath  /* get the next path */

   if (translate(substr(NextPath,3)) = '\OS2\DLL') then  /* if we see this */
   do
    Location = NextPath  /* we have our location */
   end

  end

 end

end

call stream ConfigFile,'C','CLOSE'  /* close the file */

return Location  /* end of GetDLLDir */

/**************************************************************************/
CheckDir: procedure expose Global.  /* checks the existence of a directory */
/**************************************************************************/

parse arg DirName  /* get the name of the directory to check */

OrgDir = directory()  /* store the current directory name */

if (directory(DirName) = '') then  /* if we cannot change to the directory */
do
 call WriteLog '  ERROR: Cannot find directory "'||DirName||'".'  /* report */
 return 0  /* return with an error */
end

call directory OrgDir  /* change back to the original directory */
call WriteLog '         Checked directory "'||DirName||'".'  /* report */

return 1  /* end of CheckDir */

/**************************************************************************/
MakeDir: procedure expose Global.  /* check for the existence of a dir, and if not found, create it */
/**************************************************************************/

parse arg NewDir  /* get the name of the dir to make */

call sysfiletree NewDir,'Dirs.','DO'  /* look for the dir */

if (Dirs.0 = 0) then  /* if it is not found */
do

 if (sysmkdir(NewDir) >< 0) then  /* if we cannot create the dir */
 do
  call WriteLog '  ERROR: Cannot create directory "'||NewDir||'".'  /* report */
  return 0  /* return with an error */
 end

end

return 1  /* end of MakeDir */

/**************************************************************************/
MakeFolder: procedure expose Global.  /* creates a folder */
/**************************************************************************/

parse arg Name,Location,Settings  /* get the arguments */

if (\syscreateobject('WPFolder',Name,Location,,'UPDATE')) then  /* if we cannot create (or update) the folder */
do
 call WriteLog '  ERROR: Cannot create folder "'||Name||'" in "'||Location||'".'  /* report */
 return 0  /* return with an error */
end

if (Settings >< '') then  /* if we have extra settings */
do

 if (\syssetobjectdata(Location||'\'||Name,Settings)) then  /* if we cannot change the folder's settings */
 do
  call WriteLog '  ERROR: Cannot update settings of "'||Name||'" in "'||Location||'".'  /* report */
  return 0  /* return with an error */
 end

end

call WriteLog '         Created or updated folder "'||Name||'" in "'||Location||'".'  /* report */

return 1  /* end of MakeFolder */

/**************************************************************************/
MakeObject: procedure expose Global.  /* creates a program object */
/**************************************************************************/

parse arg Title,Location,ExeName,Parameters,AssocType,ObjectID,Settings  /* get the arguments */

BaseSettings = 'EXENAME='||ExeName||';'||,  /* include the executable path and name */
               'PARAMETERS='||Parameters||';'||,  /* include the executable parameters */
               'ASSOCTYPE='||AssocType||';'||,  /* include the association type(s) */
               'TITLE='||Title||';'||,  /* change the title if we have an old object */
               'OBJECTID='||ObjectID  /* include the object ID */

if (\syscreateobject('WPProgram',Title,Location,BaseSettings,'UPDATE')) then  /* if we cannot create the program object */
do
 call WriteLog '  ERROR: Cannot create object with object ID "'||ObjectID||'" and title "'||Title||'" in "'||Location||'".'  /* report */
 return 0  /* return with an error */
end

if (Settings >< '') then  /* if we have extra settings */
do

 if (\syssetobjectdata(ObjectID,Settings)) then  /* if we cannot change the object's settings */
 do
  call WriteLog '  ERROR: Cannot update settings for object "'||Title||'" in "'||Location||'".'  /* report */
  return 0  /* return with an error */
 end

end

if (\syssaveobject(ObjectID,1)) then  /* if we cannot save the program object */
do
 call WriteLog '  ERROR: Cannot save object with object ID "'||ObjectID||'"'  /* report */
 return 0  /* return with an error */
end

call WriteLog '         Created or updated object, object ID "'||ObjectID||'" and title "'||Title||'" in "'||Location||'".'  /* report */

return 1  /* end of MakeObject */

/**************************************************************************/
MakeShadow: procedure expose Global.  /* creates a shadow */
/**************************************************************************/

parse arg Name,Location  /* get the arguments */

if (\syscreateshadow(Name,Location)) then  /* if we cannot create the shadow */
do
 call WriteLog '         Cannot create shadow of "'||Name||'" in "'||Location||'"; shadow may already exist.'  /* report */
 return 0  /* return with an error */
end

call WriteLog '         Created shadow of "'||Name||'" in "'||Location||'".'  /* report */

return 1  /* end of MakeShadow */

/**************************************************************************/
WriteLog: procedure expose Global.  /* writes an entry in the log file */
/**************************************************************************/

parse arg Text  /* get the argument */

if (stream(Global.LogFile,'C','OPEN WRITE') >< 'READY:') then  /* if we cannot open the log file for writing */
do
 call lineout 'StdOut:','ERROR: Cannot write to log file.'  /* show a message */
 return 0  /* return with an error */
end

call lineout Global.LogFile,Text  /* write the text to the file */
call stream Global.LogFile,'C','CLOSE'  /* close the file */

return 1  /* end of WriteLog */

/**************************************************************************/
GotUser: procedure expose Global.  /* looks for a user entry in the location.txt file */
/**************************************************************************/

parse arg LocFile,UserName  /* get the arguments */

if (stream(LocFile,'C','OPEN READ') >< 'READY:') then  /* if we cannot open the location file */
do
 return 0  /* return with no result */
end

GotUserName = 0  /* we haven't found it yet */

do while (lines(LocFile))  /* as long as we have lines left */

 NextLine = linein(LocFile)  /* get the next one */

 if (NextLine >< '') then  /* if the line is not empty */
 do

  if (substr(NextLine,1,1) >< '#') then  /* if it is not a comment */
  do

   parse var NextLine User ' = ' Location ';'  /* get the bits we want */

   if (translate(UserName) = translate(User)) then  /* if it is what we're looking for */
   do
    GotUserName = 1  /* we have a user name */
   end

  end

 end

end

call stream LocFile,'C','CLOSE'  /* close the locations file */

return GotUserName  /* end of GotUser */

/**************************************************************************/
GetLocations: procedure expose Global.  /* collects user entries from the location.txt file */
/**************************************************************************/

parse arg LocFile  /* get the argument */

if (stream(LocFile,'C','OPEN READ') >< 'READY:') then  /* if we cannot open the location file */
do
 return 0  /* return with no result */
end

Locations = ''  /* start with nothing */

do while (lines(LocFile))  /* as long as we have lines left */

 NextLine = linein(LocFile)  /* get the next one */

 if (NextLine >< '') then  /* if the line is not empty */
 do

  if (substr(NextLine,1,1) >< '#') then  /* if it is not a comment */
  do
   parse upper var NextLine Location ' = ' User ';'  /* get the bits we want */
   Locations = Locations||' '||Location  /* add it to what we have */
  end

 end

end

call stream LocFile,'C','CLOSE'  /* close the locations file */
Locations = strip(Locations)  /* get rid of excess whitespace */

return Locations  /* end of GetLocations */

/**************************************************************************/
StartExplain: procedure expose Global.  /* explain to the user what's going to happen */
/**************************************************************************/

if (Global.Auto) then  /* if we are in auto mode */
do
 return 1  /* quit */
end

call ClearScreen  /* clear the screen */
call lineout 'CON:','This is the RexxMail installation program.'  /* screen info */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:','This program will prompt you before making any changes to your setup.'  /* screen info */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:','A record of all the changes made by this program will be written to the'  /* screen info */
call lineout 'CON:','"install.log" file in the RexxMail program directory (i.e. the one from'  /* screen info */
call lineout 'CON:','which you are running this installation program) for future reference.'  /* screen info */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:','IMPORTANT:'  /* screen info */
call lineout 'CON:','Due to a limitation in the combination of REXX and CMD.EXE, long path'  /* screen info */
call lineout 'CON:','names can cause certain functions to fail, notably the creation of the'  /* screen info */
call lineout 'CON:','RexxMail toolbars and the application of folder background bitmaps. In'  /* screen info */
call lineout 'CON:','the event of such errors occurring, reduce the length of the path name'  /* screen info */
call lineout 'CON:','of both the RexxMail program directory and the user mail folders.'  /* screen info */
call lineout 'CON:','So, "D:\RexxMail" is preferable to "D:\Programs\Internet\Mail\RexxMail".'  /* screen info */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:','You can press [Ctrl]+[C] at any time to abort the installation program.'  /* screen info */

return 1  /* end of StartExplain */

/**************************************************************************/
WarningExplain: procedure expose Global.  /* warn against double installations */
/**************************************************************************/

if (Global.Auto) then  /* if we are in auto mode */
do
 return 1  /* quit */
end

call ClearScreen  /* clear the screen */
ScreenSize = systextscreensize()  /* get the screen dimensions */
ScreenCols = word(ScreenSize,2)  /* the screen width */
call lineout 'CON:','IMPORTANT:'  /* report */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:','Do not install RexxMail in a new directory if you already have a previous'  /* report */
call lineout 'CON:','RexxMail installation in a different program directory on your system!'  /* report */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:','If you have an active trash can object (e.g. XWP), make sure you remove'  /* report */
call lineout 'CON:','all RexxMail-related objects from it before you continue!'  /* report */

return 1  /* end of StartExplain */

/**************************************************************************/
UpdateExplain: procedure expose Global.  /* explain to the user what's going to happen when we update the program files */
/**************************************************************************/

if (Global.Auto) then  /* if we are in auto mode */
do
 return 1  /* quit */
end

call lineout 'CON:',''  /* empty line */
call lineout 'CON:','A previous version of RexxMail has been found; it will be updated.'  /* screen info */

return 1  /* end of UpdateExplain */

/**************************************************************************/
InstallExplain: procedure expose Global.  /* explain to the user what's going to happen when we install the program files */
/**************************************************************************/

if (Global.Auto) then  /* if we are in auto mode */
do
 return 1  /* quit */
end

call ClearScreen  /* clear the screen */
call lineout 'CON:','The RexxMail program files will be installed in the current directory.'  /* screen info */
call lineout 'CON:','The RexxMail icon files will be installed in an Icons subdirectory.'  /* screen info */
call lineout 'CON:','The RxMlUtil.DLL source files will be installed in a RxMlUtil subdirectory.'  /* screen info */
call lineout 'CON:','The RexxMail program objects will be created in an Objects subdirectory.'  /* screen info */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:','If you did not register the CWMailFile class before, its files will be'  /* screen info */
call lineout 'CON:','installed in a CWMailFileClass subdirectory, and you will be given the option'  /* screen info */
call lineout 'CON:','of registering the CWMailFile class. You can always (de)register the class'  /* screen info */
call lineout 'CON:','later using the utilities you will find in the CWMailFileClass subdirectory.'  /* screen info */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:','Apart from defining the file-program associations needed to make the system'  /* screen info */
call lineout 'CON:','recognize mail message files, the installation program will not change any'  /* screen info */
call lineout 'CON:','system files (like CONFIG.SYS). If you decide to register the CWMailFile'  /* screen info */
call lineout 'CON:','class, the installation program will register the functions contained in the'  /* screen info */
call lineout 'CON:','rexxmail.dll file (which you will find in the CWMailFileClass subdirectory).'  /* screen info */

return 1  /* end of InstallExplain */

/**************************************************************************/
CWMailFileExplain: procedure expose Global.  /* Explain to the user what's going to happen */
/**************************************************************************/

if (Global.Auto) then  /* if we are in auto mode */
do
 return 1  /* quit */
end

call ClearScreen  /* clear the screen */
call lineout 'CON:','The CWMailFile class has not yet been registered. Registering the class'  /* screen info */
call lineout 'CON:','will enable you to sort RexxMail messages by sender, recipients, date,'  /* screen info */
call lineout 'CON:','subject, and attachment flag in any WPS folder to which the class is'  /* screen info */
call lineout 'CON:','applied. If you register the class now, the RexxMail installation program'  /* screen info */
call lineout 'CON:','will apply the CWMailFile sorting capability to the RexxMail user folders.'  /* screen info */
call lineout 'CON:','You can always (de)register the class, and apply its sorting capability to'  /* screen info */
call lineout 'CON:','selected folders, using the utilities in the CWMailFileClass subdirectory.'  /* screen info */

return 1  /* end of CWMailFileExplain */

/**************************************************************************/
UserInstallExplain: procedure expose Global.  /* Explain to the user what's going to happen */
/**************************************************************************/

if (Global.Auto) then  /* if we are in auto mode */
do
 return 1  /* quit */
end

call ClearScreen  /* clear the screen */
call lineout 'CON:','You will now be asked for the main user directory name, which must not be'  /* screen info */
call lineout 'CON:','in the program directory, or vice versa. The directory will optionally be'  /* screen info */
call lineout 'CON:','created if it does not exist. The main directory will contain the user'  /* screen info */
call lineout 'CON:','mail folders and the Addresses, Configuration, and Temp folders.'  /* screen info */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:','IMPORTANT:'  /* screen info */
call lineout 'CON:','Due to a limitation in the combination of REXX and CMD.EXE, long path'  /* screen info */
call lineout 'CON:','names can cause certain functions to fail, notably the creation of the'  /* screen info */
call lineout 'CON:','RexxMail toolbars and the application of folder background bitmaps. In'  /* screen info */
call lineout 'CON:','the event of such errors occurring, reduce the length of the path name'  /* screen info */
call lineout 'CON:','of both the RexxMail program directory and the user mail folders.'  /* screen info */
call lineout 'CON:','So, "D:\UserMail" is preferable to "D:\Data\Internet\Mail\UserMail".'  /* screen info */

return 1  /* end of UserInstallExplain */

/*********************************************************************/
DLLExplain: procedure expose Global.  /* some info about the RxMlUtil.DLL file */
/*********************************************************************/

if (Global.Auto) then  /* if we are in auto mode */
do
 return 1  /* quit */
end

call ClearScreen  /* clear the screen */
call lineout 'CON:','RexxMail uses a small DLL for a number of basic functions that are not'  /* report */
call lineout 'CON:','provided by REXX. Before RexxMail can be used from a command line, the'  /* report */
call lineout 'CON:','RxMlUtil.DLL file must be copied to a LIBPATH directory. If you like, the'  /* report */
call lineout 'CON:','installation program can copy the file to the "OS2\DLL" directory on the'  /* report */
call lineout 'CON:','boot drive now. If you decide not to let the installation program do this,'  /* report */
call lineout 'CON:','you will have to manually copy the RxMlUtil.DLL file from the RexxMail'  /* report */
call lineout 'CON:','program directory to a directory in the LIBPATH.'  /* report */

return 1  /* end of EndExplain */

/*********************************************************************/
NoDLLExplain: procedure expose Global.  /* some info about the OS/2 DLL dir */
/*********************************************************************/

if (Global.Auto) then  /* if we are in auto mode */
do
 return 1  /* quit */
end

call ClearScreen  /* clear the screen */
call lineout 'CON:','The RexxMail installation program was unable to find the "OS2\DLL" directory'  /* report */
call lineout 'CON:','on the boot drive, so the RxMlUtil.DLL cannot be copied.'  /* report */
call lineout 'CON:','You will have to manually copy the RxMlUtil.DLL file from the RexxMail'  /* report */
call lineout 'CON:','program directory to a directory in the LIBPATH.'  /* report */

return 1  /* end of EndExplain */

/*********************************************************************/
EndExplain: procedure expose Global.  /* some final info */
/*********************************************************************/

if (Global.Auto) then  /* if we are in auto mode */
do
 return 1  /* quit */
end

call ClearScreen  /* clear the screen */
call lineout 'CON:','Installation completed.'  /* report */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:','If you plan to use RexxMail from a command line, remember to copy the'  /* report */
call lineout 'CON:','RxMlUtil.DLL file (which is in the RexxMail program directory) to a'  /* report */
call lineout 'CON:','directory in your LIBPATH.'  /* report */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:','For further instructions, please refer to the RexxMail Reference Guide.'  /* report */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:','For details, see the install.log file in the RexxMail program directory.'  /* report */

return 1  /* end of EndExplain */

/**************************************************************************/
UserQuery: procedure expose Global.  /* get a reply from the user */
/**************************************************************************/

if (Global.Auto) then  /* if we want automatic processing */
do
 return 1  /* affirm */
end

parse arg Prompt  /* get the argument */

call lineout 'CON:',''  /* start a new line */
call lineout 'CON:',''  /* start a new line */
call charout 'CON:',Prompt||' [Y/N] Y'||d2c(8)  /* user prompt */
Reply = (pos(sysgetkey('ECHO'),'Yy+'||d2c(13)) > 0)  /* affirmative = 1 */
call lineout 'CON:',''  /* start a new line */

return Reply  /* end of UserQuery */

/**************************************************************************/
UserPrompt: procedure expose Global.  /* wait for the user */
/**************************************************************************/

if (Global.Auto) then  /* if we want automatic processing */
do
 return 1  /* quit */
end

parse arg Message  /* get the argument */

call ClearScreen  /* clear the screen */
call lineout 'CON:',Message  /* report */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:',''  /* empty line */
call charout 'CON:','Press any key to continue'  /* report */
call sysgetkey 'NOECHO'  /* wait for a key */

return 1  /* end of UserPrompt */

/**************************************************************************/
ClearScreen: procedure expose Global.  /* clears the screen ("syscls" does not preserve screen colours) */
/**************************************************************************/

ScreenSize = systextscreensize()  /* get the screen dimensions */
ScreenRows = word(ScreenSize,1)  /* the screen height */
ScreenCols = word(ScreenSize,2)  /* the screen width */

do Index = 1 to ScreenRows  /* for each row on the screen */
 call syscurpos Index,0  /* move to the row start */
 call charout 'CON:',copies(' ',ScreenCols)  /* clear the line */
end

call syscurpos 0,0  /* move to the top left-hand corner of the screen */
call lineout 'CON:','RexxMail Installation Program for build '||Global.Build  /* screen info */
call lineout 'CON:',''  /* empty line */
call lineout 'CON:',''  /* empty line */

return 1  /* end of ClearScreen */

/**************************************************************************/
LoadRexxUtils: procedure expose Global.  /* Load the REXX utility functions if necessary */
/**************************************************************************/

if (rxfuncquery('SysLoadFuncs') >< 0) then  /* if we have to load the REXX utility functions */
do

 if (rxfuncadd('SysLoadFuncs','RexxUtil','SysLoadFuncs') = 0) then  /* if we can register the general loading function */
 do
  call sysloadfuncs  /* call the general loading function */
 end
 else  /* if we cannot register the general loading function */
 do
  return 0  /* no success */
 end

end

return 1  /* end of LoadRexxUtils */

/**************************************************************************/
Syntax:  /* handles syntax errors */
/**************************************************************************/

call FatalError 'REXX did not recognize the instruction',Sigl  /* start with this */
call Halt  /* and quit via Halt */

/**************************************************************************/
NoValue:  /* handles initialization errors */
/**************************************************************************/

call FatalError 'Initialization error',Sigl  /* start with this */
call Halt  /* and quit via Halt */

/**************************************************************************/
FatalError: procedure expose Global.  /* reports a fatal error */
/**************************************************************************/

parse arg ErrorStart,Sigl  /* get the argument */

call WriteLog '  ERROR : '||ErrorStart||' on line '||Sigl||':'||,  /* report */
              '    '||sourceline(Sigl)  /* report */

return 1  /* end of FatalError */

/*********************************************************************/
Halt:  /* we end up here if a halt condition occurred */
/*********************************************************************/

call beep 444,111  /* signal */
call beep 333,222  /* signal */
call WriteLog date('S')||' '||time('N')||' : Installation aborted.'  /* report */
call ClearScreen  /* clear the screen */
call lineout 'CON:','Installation aborted.'  /* show a message */

/*********************************************************************/
Quit:  /* we end up here at the end of it all */
/*********************************************************************/

call WriteLog date('S')||' '||time('N')||' : Installation completed.'  /* report */
call EndExplain  /* some info */
call UserPrompt 'The RexxMail installation has finished'  /* wait for the user if necessary */

exit  /* and exit */
