home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / Dloads / PROGRAMM / BUILDER.ZIP / INSTALL.BLD < prev    next >
Text File  |  1992-11-17  |  55KB  |  1,616 lines

  1. '==================================================================
  2. ' INSTALL.BLD
  3. '
  4. ' What it does
  5. ' ------------
  6. '   This is a complete, ready-to-use installation program.  While
  7. '   it's used to install Builder, it was designed to be easily
  8. '   dissected and altered for your own use.
  9. '   * Installation from any disk, to any disk
  10. '   * A help screen
  11. '   * Options for full vs. minimal installation (for users with
  12. '     limited disk space)
  13. '   * Data-driven:  the configuration data file can create directories,
  14. '     change to them, and prompt to change disks.  If you write your
  15. '     script correctly, you'll need to make only a few changes to the
  16. '     .BLD file.
  17. '   * Preset initial subdirectory for installation that the user can
  18. '     change
  19. '   * Tracks which files are installed and displays a complete
  20. '     status report on completion, listing which files, if any,
  21. '     didn't copy over
  22. '   * List of files to be installed in configuration data files,
  23. '     so they can be updated without changing or recompiling the
  24. '     install program
  25. '   * Configuration files may contain comments, so you can keep
  26. '     track of what files are included and why.
  27. '   * Configuration files handle disk changes
  28. '   * Configuration files may include descriptions of files to be
  29. '     printed along with the filename being copied.
  30. '   * User can interrupt installation anytime by pressing {Esc},
  31. '     or pause it by pressing {Space}.
  32. '   * User can confirm choices without continuing installation
  33. '   * User can change source drive, target drive, and target
  34. '     directory
  35. '   * Senses "disk not ready" conditions and insertion of wrong
  36. '     disks
  37. '   * Small--the compiled program requires less than 35K
  38. '   * Senses the video adaptor and sets colors accordingly
  39. '   * Detailed comments in the .BLD file explaining how to revise
  40. '     the script for your own use
  41. '   * Runs an included file viewer program called SHOW.EXE to
  42. '     display a README file
  43. '
  44. ' The following files are expected to appear in the target directory
  45. '   - Data file
  46. '   - SHOW.EXE
  47. '   The installation script copies them over.  It does not delete
  48. '   them on exit.
  49. ' Terms
  50. ' -----
  51. ' Here's an informal explanation of the terms used in this program.
  52. '
  53. ' COMMENT: A line in the data file containing the "[" character. A
  54. '   comment line is ignored by the installation program and is there
  55. '   solely for those reading through the data file.  It can be used
  56. '   to explain what the installation program does.  Example comment
  57. '   line:
  58. '     [ Builder 1.50 installation data file for 5.25" diskette installations
  59. '
  60. ' CONFIGURATION FILE: See DATA FILE
  61. '
  62. ' DATA FILE:  A file the installation program reads.  It contains the names
  63. '   of files to be installed (that is, copied to the TARGET DIRECTORY),
  64. '   COMMENT lines, DESCRIPTION lines, and commands to make and change
  65. '   TARGET DIRECTORIES.
  66. '
  67. ' DESCRIPTION LINE:  A line in the installation file that appears
  68. '   onscreen while a file is being copied.  It's displayed in boldface
  69. '   and contains the text "<bold>".  Example description line:
  70. '     <bold>The Builder command-line compiler
  71. '
  72. ' SOURCE DIRECTORY/DISK:  The diskette from which files are copied.
  73. '   These are the diskettes you send out with your installation
  74. '   program.
  75. '
  76. ' TARGET DIRECTORY:  The directory files are copied into.  There may
  77. '   be several target directories; the installation script can create
  78. '   them and change to them.
  79. '
  80. ' The installation is driven by a data file.  It lets you display
  81. ' descriptions of the files to be copied, include comments in the
  82. ' data file, and even control disk changes.
  83. '
  84. ' File format
  85. ' ----------
  86. ' * File format for the data file:
  87. '   - Lines starting with [ aren't copied or displayed. They're comment
  88. '     lines.
  89. '   - Lines starting with <bold> are description lines, and are displayed
  90. '     while the file named on the next line is copied.  Descriptions may
  91. '     be up to 45 chars and MUST be followed by a filename.  Example:
  92. '
  93. '       <bold>The Builder command-line compiler
  94. '       BLD.EXE
  95. '
  96. '   - Anything else is thought to be a file and is copied over.
  97. '   - A line containing "CHANGE_DISK" means that a new disk must be inserted.
  98. '     It must be followed by these lines:
  99. '
  100. '       1. The volume label of the disk to be inserted (you can view or
  101. '          change the volume label using DOS's LABEL command).  Make sure
  102. '          the case matches the case of the disk label (usually all uppercase).
  103. '       2. A prompt, such ask "Please insert Disk 2 of 2".
  104. '          For example, the Builder script for 5.25" diskettes involves 2
  105. '          disks, with the volume labels "DISK 1" and "DISK 2".  The lines
  106. '          in our FULL.DAT file are:
  107. '
  108. '       Change disk
  109. '       DISK 2
  110. '       Please insert the disk labeled "Disk 2 of 2".
  111. '
  112. '      If the correct diskette isn't inserted, the prompt continues until
  113. '      it is.
  114. '
  115. '   - A line containing the text "CHANGE_TARGET_DIR" should be followed by
  116. '     the name of an existing target directory.  The next line should
  117. '     contain the name of the directory to change to.  See also
  118. '     MAKE_TARGET_DIR.  Example:
  119. '       [ Change back to the original target directory.
  120. '       CHANGE_TARGET_DIR
  121. '       [ Go back to the Builder directory.
  122. '       ..
  123.  
  124. '   - A line containing the text "MAKE_TARGET_DIR" should be followed by
  125. '     the name of a target directory to be created.  The next line should
  126. '     contain the name of the directory to create.  If the target directory
  127. '     already exists, nothing is done.  If it doesn't exist, it's created.
  128. '     Example:
  129. '       [ Create the directory EXAMPLES
  130. '       MAKE_TARGET_DIR
  131. '       EXAMPLES
  132. '
  133. '   Notes
  134. '   -----
  135. '   Only description lines should contain the string "<bold>".
  136. '   Only comment lines should contain "["
  137. '   Only CHANGE_DISK lines should contain the text "CHANGE_DISK"
  138. '   Only MAKE_TARGET_DIR lines should contain the text "MAKE_TARGET_DIR".
  139. '   Only CHANGE_TARGET_DIR lines should contain the text "CHANGE_TARGET_DIR".
  140. '
  141. ' By:
  142. '   Tom Campbell, Doug Amaral
  143. '
  144. '==================================================================
  145.  
  146. ' InFile is the data file containing filenames, sizes, etc.
  147. ' CheckFile is the output file containing files that didn't make it.
  148. File InFile, CheckFile
  149.  
  150. ' BothReady is set to 1 only if both SourceDrive and TargetDrive are
  151. ' ready.
  152. ' BoxWidth is used to adjust the size of boxes.
  153. ' CorrectParams is 0 until source drive, target drive, and directory
  154. ' are okay.
  155. ' DiskStatus flags readiness of source and target drives.
  156. ' FullInstall is 1 for a full installation, 2 for minimal installation.
  157. ' InstallError is 0 if no files were installed, 1 if some were installed,
  158. '  2 if all were installed.  "All" means the set of files listed in either
  159. '  the Full or Minimal installation option, whichever was chosen.
  160. ' InstFileCount is the # of files that *should* be copied from the source
  161. '   disk to the target directory.  It's given in the install file.
  162. ' Lines in the data file starting with "]" are called description lines.
  163. ' When GetNextLine reads in such a line, IsDescription is set to 1.
  164. ' Otherwise, it's cleared to 0.
  165. ' Missing is set to the number of files that should have been copied from
  166. '   the source directory to the target directory, but somehow weren't.
  167. ' MsgLen is used for length of command line params.
  168. ' NumOfFiles is the # of files this installation procedure should copy.
  169. '   It's the first non-comment line of the installation file.
  170. ' ShouldCopy is set to 1 if the next line read from the data file is
  171. '   is a filespec that should be copied to the target.  It's cleared to 0
  172. '   for other lines, such as comments or description lines.
  173. Integer BothReady, BoxWidth, DiskStatus, CorrectParams
  174. Integer FullInstall, InstallError, InstFileCount, IsDescription
  175. Integer Missing, MsgLen, NumOfFiles, ShouldCopy
  176. Integer Copying
  177. ' LongVal is the converted value of a number read in from a file. Since
  178. '   Builder can't currently read a number directly from a file, it has
  179. '   to be converted from string to integer.  This is the value returned.
  180. longint FullSize, LongVal, MinSize
  181.  
  182. ' CorrectLabel is the label of the disk to be inserted.
  183. ' Disk1 is the volume label for disk 1 of the installation.
  184. ' DiskPrompt is used by CorrectDrive.  it's the prompt displayed for
  185. '   the user to insert a diskette.
  186. ' DriveSpec is used by the routine ValidateDrive, which makes sure
  187. ' a drive is specified correctly.
  188. ' CheckName is the name of the file that tracks which files got written
  189. '   out; it's used to verify the list of files copied once the copy
  190. '   procedure is finished.
  191. ' InstName is the name of the input data file.
  192. ' Msg is used for dialogs whose text changes.
  193. ' NextLine holds line as it's read from the install data file.
  194. ' Scratch is a general-purpose string variable. Assume its value will
  195. '   be lost between SUB invocations.
  196. ' ScreenType holds adaptor type, as returned by the Adaptor function.
  197. ' SourceDrive is the floppy Builder is installed from (defaults to A).
  198. ' Target is the drive and path where files are installed.
  199. ' TargetDir is the directory Builder will be copied to.
  200. ' TargetDrive is the volume Builder is installed to (defaults to C).
  201. ' TargetFile is the fully qualified filename of the file being copied
  202. ' to its target directory, such as "C:\BUILDER\BLD.EXE".
  203. String CheckName, CorrectLabel, Disk1, DiskPrompt, DriveSpec, InstName
  204. String Msg, NextLine, Scratch, ScreenType, SourceDrive, Target, TargetDir
  205. String TargetDrive, TargetFile, Scratch1, Hold, InputIt
  206.  
  207. ' Just change these variables to alter default values.
  208. String DefSourceDrive, DefFullFile, DefMinFile, DefTargetDrive, DefTargetDir
  209. LongInt DiskAvail,NeededSpace
  210. String CurrentDisk
  211. '==================================================================
  212. '
  213. ' 1. DEVELOPER-DEFINED VARIABLES--INITIAL SETTINGS
  214. '
  215. ' The variables initialized in this section need only be changed
  216. ' here; you can and should leave them alone in the rest of the
  217. ' program.  This localizes changes that need to be made to this
  218. ' script.  They are never changed by the user.
  219. '
  220. ' These serve the same purpose as named constants in other
  221. ' languages; since Builder currently lacks them, variables are used
  222. ' instead.
  223. '
  224. ' These variables are listed in alphabetical order within this
  225. ' section.
  226. '
  227. '==================================================================
  228.  
  229. ' Name of output file that tracks files copied.  This file will be
  230. ' deleted if all files are installed properly.
  231. CheckName := "MISSING.TXT"
  232. ' Filename used for full installation option.
  233. DefFullFile := "FULL.DAT"
  234. ' Filename used for minimal installation option.
  235. DefMinFile := "MINI.DAT"
  236. ' Volume label of the first distribution diskette.
  237. Disk1 := "DISK 1"
  238.  
  239. '==================================================================
  240. '
  241. ' 2. USER-DEFINED VARIABLES--INITIAL SETTINGS
  242. '
  243. ' The variables initialized in this section need only be changed
  244. ' here; you can and should leave them alone in the rest of the
  245. ' program.  This localizes changes that need to be made to this
  246. ' script.
  247. '
  248. ' The installation script offers the user to change them at the
  249. ' appropriate time; they consist of things like directory names
  250. ' and the drive letters of disk used to copy from (never
  251. ' hard code values like the disk used to copy from).
  252. '
  253. ' These variables are listed in alphabetical order within this
  254. ' section.
  255. '
  256. '==================================================================
  257.  
  258. ' Drive to install from (the user can change this later).
  259. DefSourceDrive := "A"
  260. ' Drive to install to (the user can change this later).
  261. DefTargetDrive := "C"
  262. ' Directory to install to (the user can change this later).
  263. DefTargetDir := "\BUILDER"
  264.  
  265.  
  266. '==================================================================
  267. '
  268. ' These initializations should be left as is, with the possible
  269. ' exception of Target.
  270. '
  271. '==================================================================
  272.  
  273. ' 0 if no files copied, 1 if some files copied, 2 if all copied.
  274. InstallError := 0
  275. ' Value of next integer read in from file. Set to known quantity.
  276. LongVal := 0
  277. ScreenType:=Adaptor
  278.  
  279. ' Missing is set to the number of files that should have been copied from
  280. ' the source directory to the target directory, but somehow weren't.
  281. ' Starts off at 0, of course.
  282. Missing := 0
  283. ' Full pathane of directory to install to.
  284. Target := DefTargetDrive + ":" + DefTargetDir
  285.  
  286. SetMenuColors
  287.  
  288. ' Collect any command line parameters and force them to uppercase.
  289. Put UpperCase "%1" Into SourceDrive
  290. Put UpperCase "%2" Into TargetDrive
  291. Put UpperCase "%3" into TargetDir
  292.  
  293. ' If any params were missing, fill in with reasonable defaults.
  294. if SourceDrive is "" SourceDrive := DefSourceDrive
  295. if TargetDrive is "" TargetDrive := DefTargetDrive
  296. if TargetDir is "" TargetDir := DefTargetDir
  297.  
  298. CurrentDisk:=CurrentDrive
  299. If ((CurrentDisk=="B:") AND ("%1"=="")) SourceDrive:="B"
  300.  
  301.  
  302. 'Check to see if the drives have no colons and if the directory has a leading
  303. 'backslash
  304. if (SourceDrive Contains ":") SourceDrive:= MidStr SourceDrive,1,1
  305. if (TargetDrive Contains ":") TargetDrive:= MidStr TargetDrive,1,1
  306. 'Grab the first character of the string
  307. Hold:= Midstr TargetDir,1,1
  308. 'Insert a leading backslash if one does not exist
  309. if Hold<>"\" TargetDir:="\"+TargetDir
  310.  
  311. ' Assume user input, if any, is incorrect.
  312. Put 0 into CorrectParams
  313.  
  314. ' Assume full installation.
  315. Put 1 into FullInstall
  316.  
  317. ' Initialize for the very first call to RedrawMsgArea
  318. SetMenuColors
  319. BoxWidth := 30
  320. ' Put up the banner and menu's help.
  321. RedrawMsgArea
  322.  
  323. ' This is the main loop.
  324. While 1
  325.   ' Use the standard white text on a black background if it's a mono
  326.   ' screen.
  327.   If ScreenType is "Mono"
  328.     CLS
  329.   end else
  330.     ' If it's a color screen, use a blue background.
  331.     CLS White On Blue
  332.   end
  333.   ' Display title for this program.
  334.   RedrawMsgArea
  335.   ' Create a dropdown menu in the middle of the screen. No title.
  336.   DoMainMenu
  337. End
  338.  
  339. ' Displays main menu and dispatches input.  Does it only once; another
  340. ' loop must repeat this process until Quit command is issued.
  341. Sub DoMainMenu
  342.   ' Adjust menu colors to screen type.
  343.   SetMenuColors
  344.   ' The menu is a box--no title--in the center of the screen.
  345.   Dropdown "" @ 8, 29
  346.     Item "Full Installation"
  347.       ' Use full, not minimal, installation.
  348.       Put 1 into FullInstall
  349.       Put 1100000 into NeededSpace
  350.       DoInstall
  351.     Item "Minimum Installation"
  352.       Put 2 into FullInstall
  353.       Put 950000 into NeededSpace
  354.       DoInstall
  355.     Item "Help"
  356.       DoHelp
  357.     Item "Show choices"
  358.       ' Disable hardware text cursor.
  359.       Don't use cursor
  360.       DisplayParams
  361.       GetKey
  362.       Use cursor
  363. '    Item "Documentation Update"
  364. '      run show readme.txt
  365.     Item "Quit"
  366.       CloseUp
  367.   End ' DropDown
  368. End ' Sub DoMainMenu
  369.  
  370. '==================================================================
  371. ' 3. SUB DoHelp -- CHANGE THIS TO SUIT YOUR OWN APPLICATION
  372. '
  373. ' What it does:
  374. '   Displays a single help screen.  Draws a box in color if it's a
  375. '   color system and BW if it's a mono system.
  376. '
  377. ' Globals affected:
  378. '   STRING ScreenType
  379. '
  380. '==================================================================
  381.  
  382. Sub DoHelp
  383.   ' Disable hardware text cursor.
  384.   Don't use cursor
  385.   ' Draw a white on black box in a mono system.
  386.   If ScreenType contains "Mono"
  387.     Single Box 6, 5, 72, 15 White on Black
  388.     Text Bright White on Black
  389.   ' Draw a yellow on black box in a color system.
  390.   end else
  391.     Single Box 6, 5, 72, 15 Blue on White
  392.     Text Blue on White
  393.   end
  394.  
  395.  
  396.   Say @ 7, 31 "<black>About installation"
  397.   Say @ 9,  9 "Full installation:     Builder and example directory (1.1M)"
  398.   Say @ 10, 9 "Minimum installation:  Builder and help files only (950K)"
  399. '  Say @ 11, 9 "Documentation Update:  Bug list and new features"
  400.   Say @ 11, 9 "Quit:                  Exit this installation program."
  401.   Say @ 15, 9 "To make a choice, move the {Up} or {Down} keys and press {Enter}."
  402.   Say @ 16, 9 "If you have a mouse, click the left button on the appropriate"
  403.   Say @ 17, 9 "choice."
  404.   Say @ 19,23 "<reverse> Press {Enter} to return to main menu ";
  405.  
  406.   GetKey
  407.  
  408. End ' Sub DoHelp
  409.  
  410.  
  411. '==================================================================
  412. ' SUB ChangeDisk
  413. '
  414. ' What it does:
  415. '   Responds to a "CHANGE_DISK" line.  Expects that the next lines
  416. '   will be a volume label, then a prompt.  Displays the prompt,
  417. '   then waits for a disk with that volume label to be inserted.
  418. '   If the wrong disk is inserted, redisplays the prompt.
  419. '
  420. ' Globals affected:
  421. '   STRING Msg, NextLine
  422. '
  423. ' Other routines called:
  424. '   GetNextLine
  425. '
  426. '==================================================================
  427.  
  428. Sub ChangeDisk
  429.   ' Get the next non-comment line from the disk and copy to the
  430.   ' variable NextLine.
  431.   GetNextLine
  432.   ' This is the volume to check.
  433.   CorrectLabel := NextLine
  434.  
  435.   ' Get the next non-comment line from the disk and copy to the
  436.   ' variable DiskPrompt.
  437.   GetNextLine
  438.   ' This is the volume to check.
  439.   DiskPrompt := NextLine
  440.   ' Loop until the correct disk is inserted or user presses {Esc}.
  441.   BothReady := 0
  442.   While BothReady is 0
  443.     CorrectDrive
  444.   End
  445.       Double Box 17, 7, 68, 9 White on Black
  446.       Text Bright White on black
  447.       say @ 18, 9 "<bold>Now copying files. Press {Space} to pause or {Esc} to quit."
  448.  
  449. End ' Sub ChangeDisk
  450.  
  451. '==================================================================
  452. ' SUB CheckDrives
  453. '
  454. ' What it does:
  455. '   Checks both source and target drives.
  456. '   Displays an error message for each drive that's not ready.
  457. '   If both are ready, sets BothReady to 1.  If either is not
  458. '   ready, sets it to 0.
  459. '
  460. ' Globals affected:
  461. '   INTEGER BothReady, DiskStatus
  462. '   STRING Msg, SourceDrive, TargetDrive
  463. '
  464. ' Other routines called:
  465. '   ErrMsg
  466. '
  467. '==================================================================
  468.  
  469. Sub CheckDrives
  470.   ' Assume at least 1 drive isn't ready.
  471.   Put 0 into BothReady
  472.   ' Check floppy we're supposed to install from.
  473.   Put DiskReady SourceDrive into DiskStatus
  474.   ' Check floppy for readiness.
  475.   If DiskStatus is 0
  476.     ' Put up an error dialog if it's not ready.
  477.     Msg := "Disk " + SourceDrive + " isn't ready."
  478.     ErrMsg
  479.   end else
  480.     ' Check the directory files will be copied to.
  481.     Put DiskReady TargetDrive into DiskStatus
  482.     ' Display an error message if the target drive isn't ready.
  483.     If DiskStatus is 0
  484.       Msg := "Disk " + TargetDrive + " isn't ready."
  485.       ErrMsg
  486.     end else
  487.       ' Both are ready, so give it the go-ahead.
  488.       While CorrectParams is 0
  489.       ' Ask if that's the drive to install to.
  490.        Msg := "Copy files to drive " + TargetDrive + "? (Y/N)"
  491.        GetYNMessage
  492.       ' Assume user input will be bad.
  493.       ' Repeat until input is valid.
  494.        ' If user pressed, Y, then assume this is correct input.
  495.        If DOSErrorLevel is 1
  496.          Put 1 into CorrectParams
  497.        end else
  498.          Put 0 into CorrectParams
  499.          Put "Drive to copy files to? " into Msg
  500.          InputDriveLetter
  501.          TargetDrive := DriveSpec
  502.        End ' If DOSERRORLEVEL
  503.      End ' While CorrectParams
  504.       Put 1 into BothReady
  505.     End ' If DiskStatus
  506.   End ' If DiskStatus
  507. End ' Sub CheckDrives
  508.  
  509. '==================================================================
  510. ' SUB CheckPause
  511. '
  512. ' What it does:
  513. '   Checks for a keypress.  If no keypress, cool.  If the keypress
  514. '   is {Esc}, halts installation process.  If the keypress is the
  515. '   space bar, asks the user to halt installation and quits if
  516. '   user types {Y}.
  517. '
  518. ' Globals affected:
  519. '   INTEGER BoxWidth
  520. '   STRING Msg
  521. '
  522. ' Other routines called:
  523. '   GetYNMessage
  524. '
  525. '==================================================================
  526.  
  527. Sub CheckPause
  528.   ' Quit this routine if no key was pressed.
  529.   if Keypressed
  530.     ' A key was pressed.  Remove it from the keyboard buffer.
  531.     GetKey
  532.     ' Quit immediately if it's the {Esc} key.
  533.     If LastKey is {Esc} CloseUp
  534.     ' If it's the space bar,
  535.     If LastKey is { }
  536.       ' ask the user if she wants to quit.
  537.       Msg := "Would you like to cancel installation? (Y/N)"
  538.       GetYNMessage
  539.       ' If user pressed, Y, then quit.
  540.       If DOSErrorLevel is 1
  541.         CloseUp
  542.       end ' If DOSErrorLevel
  543.       Double Box 17, 7, 68, 9 White on Black
  544.       Text Bright White on black
  545.       say @ 18, 9 "<bold>Now copying files. Press {Space} to pause or {Esc} to quit."
  546.  
  547.     end ' If Lastkey
  548.   end ' If Keypressed
  549. End ' Sub CheckPause
  550.  
  551. '==================================================================
  552. ' SUB CloseUp
  553. '
  554. ' What it does:
  555. '   Displays a sign-off message at the top of the screen.
  556. '   Writes an EOF to CheckFile, since SHOW.EXE requires it.
  557. '   Closes all files.
  558. '   Deletes the check file (which contains the list of missing
  559. '   files) if none is missing.
  560. '
  561. ' Globals used:
  562. '   INTEGER Missing
  563. '
  564. ' Other routines called:
  565. '   GetYNMessage
  566. '
  567. '==================================================================
  568.  
  569. Sub CloseUp
  570.   If Missing
  571.     ' Convert the # of files that didn't make it to an integer.
  572.     Msg := IntToStr Missing
  573.     Msg := Msg + " files weren't copied over.  View the list of those missing files? "
  574.     GetYNMessage
  575.     If DOSErrorLevel is 1
  576.       ' Write an EOF to the list of missing files, if any.
  577.       WriteLine "~26" to CheckFile
  578.       System Target+"\Show " + Target+"\"+CheckName
  579.     End
  580.   end else
  581.     ' No files missing. Delete that file.
  582.     System "if exist " + CheckName + " del " + CheckName
  583.   End ' If Missing
  584.   ' Clear the screen.
  585.   cls
  586.   ' Print sign-off message
  587.   SayGoodbye
  588.   ' Restore the text cursor.
  589.   Use cursor
  590.   ' Return all file resources to DOS.
  591.   CloseAllFiles
  592.   ' Return to the operating system.
  593.   Exit
  594. End ' Sub Closeup
  595.  
  596. '==================================================================
  597. ' SUB CorrectDrive
  598. '
  599. ' What it does:
  600. '   Checks DriveSpec for CorrectLabel.  If the disk in DriveSpec
  601. '   has the wrong label, puts up an error message, and sets
  602. '   BothReady to 0.  Otherwise, sets BothReady to 1.
  603. '
  604. '   If user presses {Esc}, quits the program by calling CloseUp.
  605. '
  606. ' Globals affected:
  607. '   INTEGER BothReady
  608. '   STRING CorrectLabel, DiskPrompt, DriveSpec, Msg, SourceDrive
  609. '
  610. ' Other routines called:
  611. '   CloseUp, ErrMsg, ShowMsgBox
  612. '
  613. '==================================================================
  614.  
  615. Sub CorrectDrive
  616.   ' Get the label of the disk in the drive being installed from.
  617.     ' Get its label.
  618.     Put DiskLabel SourceDrive into DriveSpec
  619.     ' Is it the correct one?
  620.     If DriveSpec <> CorrectLabel
  621.       ' Nope. Issue an error message.
  622.       Msg := DiskPrompt
  623.       ShowMsgBox
  624.       ' Set error flag.
  625.       Put 0 into BothReady
  626.     end else
  627.       ' Correct disk was inserted. Everything's cool.
  628.       Put 1 into BothReady
  629.     End
  630.     ' Quit if user pressed {Esc}.
  631.     If LastKey is {Esc} CloseUp
  632. End ' Sub CorrectDrive
  633.  
  634.  
  635. '==================================================================
  636. ' SUB CreateDirectories
  637. '
  638. ' What it does:
  639. '   Creates the target directory, whose name is in Target and
  640. '   sets DiskStatus to 1.  If unable to create the target
  641. '   directory, sets DiskStatus to 0.
  642. '
  643. ' Globals affected:
  644. '   INTEGER DiskStatus
  645. '   STRING Target
  646. '
  647. ' Other routines called:
  648. '   ErrMsg
  649. '
  650. '==================================================================
  651.  
  652. Sub CreateDirectories
  653.   ' MD will issue a non-redirectable error message if the directory
  654.   ' already exists, so check for it first.  DiskStatus will be 1 if
  655.   ' the directory is already there, and 0 if not.
  656.   DiskStatus := DirExists Target
  657.   ' Create the directory if it's not there already.
  658.   If DiskStatus is 0
  659.     System "MD " + Target + " >nul"
  660.   end 
  661.   ' Just to be on the safe side, make sure the directory is there.
  662.   ' By all rights it should be.
  663.   Put DirExists Target into DiskStatus
  664. End ' Sub CreateDirectories
  665.  
  666. '==================================================================
  667. ' SUB DisplayParams
  668. '
  669. ' What it does:
  670. '   Display options for SourceDrive, TargetDir, TargetDrive and
  671. '   installation option (Full or Minimal).
  672. '
  673. '==================================================================
  674.  
  675. Sub DisplayParams
  676.   ' Draw a long box (long enough to hold pathnames) below the menu.
  677.   Double Box 17, 7, 68, 9 White on Black
  678.   Text Bright White on black
  679.   say @ 18, 23 "<yellow>Confirming your installation options:"
  680.   say @ 20, 9 "Install from drive <bold>"; SourceDrive; ":"
  681.   say @ 21, 9 "Copy files to <bold>"; Target
  682.   If FullInstall == 1
  683.     say @ 22, 9 "Installation: <bold>Full";
  684.   end else
  685.     say @ 22, 9 "Installation: <bold>Minimum";
  686.   End ' If FullInstall
  687. End ' Sub DisplayParams
  688.  
  689. '==================================================================
  690. ' SUB ErrMsg
  691. '
  692. ' What it does:
  693. '   Displays a box in the upper left of the screen. Prints
  694. '   "Problem:" at the top, then displays Msg in the box.  Prints
  695. '   "Press {Enter} to continue" at the bottom of the box, then
  696. '   waits for a keypress.  Draws a blank box over this one at the
  697. '   end, thus reblanking that portion of the screen.
  698. '
  699. ' Globals affected:
  700. '   INTEGER BoxWidth
  701. '   STRING Msg
  702. '
  703. '==================================================================
  704.  
  705. Sub ErrMsg
  706.   ' Disable hardware text cursor.
  707.   Don't use cursor
  708.   ' Get the length of the string in Msg and write it to BoxWidth, so the
  709.   ' width of the box can be customized.
  710.   Put Length Msg into BoxWidth
  711.   ' Account for word "<bold>Problem: "
  712.   BoxWidth := BoxWidth + 10
  713.   ' Make sure it's wide enough for the "Press" message.
  714.   If BoxWidth < 26 Put 26 into BoxWidth
  715.   ' Draw a box in the upper left corner.
  716.   Put BoxWidth + 4 into BoxWidth
  717.   Double Box 2, 2, BoxWidth, 5 Bright White on Black
  718.   ' Use bright white text on a black background.
  719.   Text Bright White on Black
  720.   Say @ 3, 4  "<bold>Problem: ";
  721.   ' Display the message starting at the left side of the box, leaving a
  722.   ' space of breathing room.
  723.   Say Msg;
  724.   Say @ 5, 4  "<bold>Press {Enter} to continue.";
  725.   ' Await a keystroke.
  726.   GetKey
  727.   ' Redraw over the box.
  728.   RedrawMsgArea
  729.   ' Enable hardware text cursor.
  730.   Use cursor
  731. End ' Sub ErrMsg
  732.  
  733. '==================================================================
  734. ' SUB GetAndConfirmParams
  735. '
  736. ' What it does:
  737. '   Calls GetParams to get and verify user's choices of source
  738. '   drive, target drive, etc., then shows them using DisplayParams
  739. '   and requests confirmation. If user confirms choices fine; if
  740. '   not, asks for them again.
  741. '
  742. ' Globals affected:
  743. '   INTEGER CorrectParams
  744. '
  745. ' Other routines called:
  746. '   GetParams, DisplayParams
  747. '
  748. '==================================================================
  749.  
  750. Sub GetAndConfirmParams
  751.   ' Assume the parameters will be changed.
  752.   Put 0 into CorrectParams
  753.   While CorrectParams is 0
  754.     ' Get user's choices.
  755.     GetParams
  756.     ' Show them.
  757.     DisplayParams
  758.     Say @ 24, 28 "<reverse>Are these correct? (Y/N) ";
  759.     GetYN
  760.     ' Can't use IF ERRORLEVEL because we need an ELSE.
  761.     If DOSErrorLevel is 1
  762.       Put 1 into CorrectParams
  763.     end else
  764.       Put 0 into CorrectParams
  765.     End
  766.   End
  767. End ' Sub GetAndConfirmParams
  768.  
  769. '==================================================================
  770. ' SUB GetDrives
  771. '
  772. ' What it does:
  773. '   Gets input for SourceDrive and TargetDrive.  It doesn't check
  774. '   for valid drives, but it does check that there's input for each
  775. '   one.  If there's input for each one, puts 1 into CorrectParams.
  776. '   If one or more is missing, puts 0 into CorrectParams.
  777. '
  778. ' Globals affected:
  779. '   INTEGER CorrectParams
  780. '   STRING DriveSpec, SourceDrive, TargetDrive
  781. '
  782. ' Other routines called:
  783. '   GetYNMessage, InputDriveLetter
  784. '
  785. '
  786. '==================================================================
  787.  
  788. Sub GetDrives
  789.  
  790.   ' Ask if that's the drive to install from.
  791.   Msg := "Install from drive " + SourceDrive + "? (Y/N)"
  792.   GetYNMessage
  793.  
  794.   ' Assume user input will be bad.
  795.   Put 0 into CorrectParams
  796.   ' Repeat until input is valid.
  797.   While CorrectParams is 0
  798.       ' If user pressed, Y, then assume this is correct input.
  799.       If DOSErrorLevel is 1
  800.         Put 1 into CorrectParams
  801.       end else
  802.         Put 0 into CorrectParams
  803.         Put "Drive to install from? " into Msg
  804.         InputDriveLetter
  805.         SourceDrive := DriveSpec
  806.       End ' If DOSERRORLEVEL
  807.   End ' While CorrectParams
  808.  
  809.   ' Ask if that's the drive to install to.
  810.   Msg := "Copy files to drive " + TargetDrive + "? (Y/N)"
  811.   GetYNMessage
  812.  
  813.   ' Assume user input will be bad.
  814.   Put 0 into CorrectParams
  815.   ' Repeat until input is valid.
  816.   While CorrectParams is 0
  817.       ' If user pressed, Y, then assume this is correct input.
  818.       If DOSErrorLevel is 1
  819.         Put 1 into CorrectParams
  820.          DiskAvail:=DiskFree TargetDrive
  821.          if DiskAvail < NeededSpace
  822.           Msg := "Not Enough room on "+TargetDrive+" to install"
  823.           ErrMsg
  824.           Put 0 into CorrectParams
  825.          end
  826.  
  827.       end else
  828.         Put 0 into CorrectParams
  829.         Put "Drive to copy files to? " into Msg
  830.         InputDriveLetter
  831.         TargetDrive := DriveSpec
  832.       End ' If DOSERRORLEVEL
  833.   End ' While CorrectParams
  834.  
  835. End ' Sub GetDrives
  836.  
  837. '==================================================================
  838. ' SUB GetDirectory
  839. '
  840. ' What it does:
  841. '   Puts up a box, requesting the name of a directory.
  842. '   Returns 1 in CorrectParams if a valid dir is entered, 0 if not.
  843. '   Writes directory name to TargetDir.
  844. '
  845. ' Globals affected:
  846. '   INTEGER CorrectParams
  847. '   STRING Msg, TargetDir
  848. '
  849. ' Other routines called:
  850. '   ErrMsg, GetYNMessage
  851. '
  852. '==================================================================
  853.  
  854. Sub GetDirectory
  855.     ' Assume bad input.
  856.     Put 0 into CorrectParams
  857.  
  858.     While TargetDir is ""
  859.       Msg := "Copy to what directory? Examples: \BUILDER or \UTIL\BUILDER"
  860.       GetString
  861.       TargetDir := InputIt
  862.       If TargetDir is ""
  863.         Put 0 into CorrectParams
  864.         Msg := "You must enter a path.  Examples: \BUILDER or \UTILS\NEW\BUILDER"
  865.         ErrMsg
  866.         TargetDir := ""
  867.       end
  868.     End
  869.  
  870.     If TargetDir contains ":"
  871.        Msg := "Please don't include a drive specification. Just a directory."
  872.        ErrMsg
  873.        Put "" into TargetDir
  874.     end else
  875.       Put 1 into CorrectParams
  876.     End ' If TargetDir
  877.  
  878.     'Grab the first character of the string
  879.     Hold:= Midstr TargetDir,1,1
  880.     'Insert a leading backslash if one does not exist
  881.     if NOT (Hold=="\") TargetDir:="\"+TargetDir
  882.  
  883.     ' Force directory name to uppercase.
  884.     Put UpperCase TargetDir into TargetDir
  885.  
  886.     If TargetDir <> ""
  887.       ' Ask if that's the directory to install to.
  888.       Msg := "Install to directory " + TargetDir + "? (Y/N)"
  889.       GetYNMessage
  890.       ' If user pressed, Y, then assume this is correct input.
  891.       If DOSErrorLevel is 1
  892.         Put 1 into CorrectParams
  893.       end else
  894.         Put 0 into CorrectParams
  895.         Put "" into TargetDir
  896.       End ' If DOSERRORLEVEL
  897.     End ' If TargetDir
  898. End ' Sub GetDirectory
  899.  
  900. '==================================================================
  901. ' SUB GetNextLine
  902. '
  903. ' What it does:
  904. '   Gets the next line from the file and copies it to the string
  905. '   variable NextLine.  If the line contains "[", which is illegal
  906. '   in a filename, it's thrown out and another line is read in.
  907. '   Use this each time you need to get information from the file,
  908. '   since a comment line can appear anywhere.
  909. '
  910. '   If the line contains "<bold>", the IsDescription flag is set
  911. '   to 1.  If not, it's set to 0.  If the line is a filespec
  912. '   that should be copied to the target, ShouldCopy is set to 1.
  913. '   If it's anything else, such as a description or comment
  914. '   line, ShouldCopy is cleared to 0.
  915. '
  916. '   If the line contains "CHANGE_DISK", calls ChangeDisk.
  917. '
  918. ' Globals affected:
  919. '   FILE Infile
  920. '   INTEGER IsDescription, MsgLen, ShouldCopy
  921. '   STRING Msg, NextLine
  922. '
  923. '==================================================================
  924.  
  925. Sub GetNextLine
  926.   ' Read a line of text from the file whose descriptor is
  927.   ' InFile. Copy it to the string variable NextLine.
  928.   If not eof InFile ReadLine NextLine from Infile
  929.   ' Strip out this an all succeeding comment lines if it starts with the
  930.   ' comment character.
  931.   While NextLine contains "["
  932.     ' As long as there's an asterisk anywhere in the line, throw
  933.     ' the line out and collect another one.
  934.     If not eof InFile ReadLine NextLine from Infile
  935.     ' This line should not be copied to the target.
  936.     Put 0 into ShouldCopy
  937.   end ' While NextLine
  938.  
  939.   ' Assume this line should be copied over--that it's a valid
  940.   ' filespec.
  941.   Put 1 into ShouldCopy
  942.   ' Assume it's not a description line.
  943.   Put 0 into IsDescription
  944.   ' Not a comment line.  Force it to uppercase.
  945.   Put UpperCase NextLine into Scratch
  946.  
  947.   ' Flag whether it's a description line.
  948.   If Scratch contains "<BOLD>"
  949.     Put 1 into IsDescription
  950.     ' This line should not be copied to the target.
  951.     Put 0 into ShouldCopy
  952.   end
  953.  
  954.   if Scratch Contains "CHANGE_DISK"
  955.     ChangeDisk
  956.     Put "" into NextLine
  957.     Put 0 into IsDescription
  958.     Put 0 into ShouldCopy
  959.   end
  960.  
  961.   if Scratch Contains "MAKE_TARGET_DIR"
  962.     MakeDir
  963.     Put "" into NextLine
  964.     Put 0 into IsDescription
  965.     Put 0 into ShouldCopy
  966.   end
  967.  
  968.   if Scratch Contains "CHANGE_TARGET_DIR"
  969.     ChangeDir
  970.     Put "" into NextLine
  971.     Put 0 into IsDescription
  972.     Put 0 into ShouldCopy
  973.   end
  974.  
  975.   if Scratch Contains "RUN_EXTRACTION"
  976.     Extraction
  977.     Put "" into NextLine
  978.     Put 0 into IsDescription
  979.     Put 0 into ShouldCopy
  980.   end
  981.  
  982.  
  983.   ' If the line is empty, don't copy.
  984.   MsgLen := Length NextLine
  985.   If MsgLen is 0
  986.     Put "" into NextLine
  987.     Put 0 into ShouldCopy
  988.     Put 0 into IsDescription
  989.   end
  990. End ' Sub GetNextLine
  991.  
  992. '==================================================================
  993. ' SUB GetParams
  994. '
  995. ' What it does:
  996. '   Ensures there is some sort of input in SourceDrive and
  997. '   TargetDrive. If not, calls GetDrives.  Once that input has been
  998. '   secured, it's checked here.  Does same for TargetDir; if none
  999. '   is given, gets one and validates it.
  1000. '
  1001. ' Globals affected:
  1002. '   INTEGER CorrectParams
  1003. '   STRING Target, TargetDir, TargetDrive
  1004. '
  1005. ' Other routines called:
  1006. '   GetDirectory, GetDrives
  1007. '
  1008. '==================================================================
  1009.  
  1010. Sub GetParams
  1011.   ' Make sure at least that SourceDrive, TargetDrive are input.
  1012.   ' Ensure they're valid.
  1013.   ' Assume the drive specs are invalid.
  1014.   Put 0 into CorrectParams
  1015.  
  1016.   ' Keep trying until valid drive letters are input.
  1017.   While CorrectParams is 0
  1018.     ' GetDrives writes 1 to CorrectParams when drive specs are valid.
  1019.     GetDrives
  1020.   End
  1021.  
  1022.   ' Keep trying until a target directory has been input.
  1023.   Put 0 into CorrectParams
  1024.   While CorrectParams is 0
  1025.     GetDirectory
  1026.   End
  1027.  
  1028.   ' Create a full path for the install files to be copied to.
  1029.   ' For example: C:BUILDER
  1030.   Put TargetDrive + ":" + TargetDir into Target
  1031.  
  1032. End ' Sub GetParams
  1033.  
  1034. '==================================================================
  1035. ' SUB GetString
  1036. '
  1037. ' What it does:
  1038. '   Displays a box in the upper left of the screen.
  1039. '   Displays Msg in the box. Awaits user input of a string.
  1040. '   Draws a blank box over this one at the end, thus reblanking
  1041. '   that portion of the screen.  Returns string in system variable
  1042. '   It.
  1043. '
  1044. ' Globals affected:
  1045. '   INTEGER BoxWidth
  1046. '   STRING Msg
  1047. '
  1048. '==================================================================
  1049.  
  1050. Sub GetString
  1051.   ' Get the length of the string in Msg and write it to BoxWidth, so the
  1052.   ' width of the box can be customized.
  1053.   Put Length Msg into BoxWidth
  1054.   ' Make sure it's wide enough for the "Press" message.
  1055.   If BoxWidth < 26 Put 26 into BoxWidth
  1056.   ' Draw a box in the upper left corner.
  1057.   ' Add 40 for the string.
  1058.   Put BoxWidth + 4 + 40 into BoxWidth
  1059.   ' Make sure box isn't too wide.
  1060.   If BoxWidth > 77 Put 77 into BoxWidth
  1061.   Double Box 2, 2, BoxWidth, 7 Bright White on Black
  1062.   ' Use bright white text on a black background.
  1063.   Text Bright White on Black
  1064.   ' Display the message starting at the left side of the box, leaving a
  1065.   ' space of breathing room.
  1066.   Say @ 5, 4 Msg;
  1067.   RowCol 6, 4
  1068.   Repeat 50
  1069.     ' This is Alt-249
  1070.     Say "∙";
  1071.   End
  1072.   RowCol 6, 4
  1073.   ' Get the string from the keyboard.
  1074.   input InputIt
  1075.   ' Redraw over the box.
  1076.   RedrawMsgArea
  1077. End ' GetString
  1078.  
  1079. '==================================================================
  1080. ' SUB GetYNMessage
  1081. '
  1082. ' What it does:
  1083. '   Displays Msg in a custom-sized box.  Appends a space.
  1084. '   Awaits a {Y} or {N} keypress.
  1085. '   Undraws box after user types {Y} or {N}.
  1086. '   If User types {Y}
  1087. '
  1088. ' Globals affected:
  1089. '   INTEGER BoxWidth
  1090. '   STRING Msg
  1091. '
  1092. ' Other routines called:
  1093. '   GetYN
  1094. '
  1095. '==================================================================
  1096.  
  1097. Sub GetYNMessage
  1098.   ' Get the length of the string in Msg and write it to BoxWidth, so the
  1099.   ' width of the box can be customized.
  1100.   Put Length Msg into BoxWidth
  1101.   ' Add for padding on left & right, as well as box sides.
  1102.   Put BoxWidth + 6 into BoxWidth
  1103.   ' Make sure box isn't too wide.
  1104.   If BoxWidth > 77 Put 77 into BoxWidth
  1105.   Double Box 2, 2, BoxWidth, 7 Bright White on Black
  1106.   ' Use bright white text on a black background.
  1107.   Text Bright White on Black
  1108.   ' Display the message starting at the left side of the box, leaving a
  1109.   ' space of breathing room.
  1110.   Say @ 5, 4 Msg + " ";
  1111.   GetYN
  1112.   ' Redraw over the box.
  1113.   RedrawMsgArea
  1114. End ' Sub GetYNMessage
  1115.  
  1116. '==================================================================
  1117. ' SUB InputDriveLetter
  1118. '
  1119. ' What it does:
  1120. '   Displays Msg in a box, then awaits input.  If input is null or
  1121. '   invalid, keeps going until valid input (consisting of a single
  1122. '   drive letter) is received.  String is copied to DriveSpec. Sets
  1123. '   CorrectParams to 0 on error, 1 on success.
  1124. '
  1125. ' Globals affected:
  1126. '   INTEGER CorrectParams
  1127. '   STRING DriveSpec
  1128. '
  1129. ' Other routines called:
  1130. '   GetString, ValidateDrive
  1131. '
  1132. '==================================================================
  1133.  
  1134. Sub InputDriveLetter
  1135.   ' Display Msg, get a string from keyboard, and copy into system global It.
  1136.   GetString
  1137.   ' Copy to temporary.
  1138.   DriveSpec := InputIt
  1139.   ' Make sure DriveSpec is valid.
  1140.   ValidateDrive
  1141.   ' Force to uppercase.
  1142.   Put Uppercase DriveSpec into DriveSpec
  1143.   if CorrectParams is 0
  1144.     Msg := "Please enter a drive letter with no colon."
  1145.     ' Display error message in a dialog and await a keypress.
  1146.     ErrMsg
  1147.   End ' If
  1148. End ' Sub InputDriveLetter
  1149.  
  1150. '==================================================================
  1151. ' SUB SetMenuColors
  1152. '
  1153. ' What it does:
  1154. '   Set menu style to B&W combination for mono systems, or a more
  1155. '   patriotic red/white/blue color set for other systems.
  1156. '
  1157. ' Globals affected:
  1158. '   STRING ScreenType
  1159. '
  1160. '==================================================================
  1161.  
  1162. Sub SetMenuColors
  1163.   If ScreenType is "Mono"
  1164.  
  1165.     ' Item text:            Black
  1166.     ' Item background:      White
  1167.     ' Hotkey text:          Black
  1168.     ' Hotkey background:    White
  1169.     ' Highlight text:       White
  1170.     ' Highlight background: Black
  1171.     ' Immediate trigger:    Off (requires {Enter} key
  1172.     ' First key is trigger: Yes
  1173.     ' Box style:            Single
  1174.     ' Shadow:               Yes
  1175.     Menu Style Black,White,Black,White,White,Black,Black,White,0,1,1,1
  1176.  
  1177.  
  1178.   end else
  1179.  
  1180.     Menu Style Blue,White,Red,White,White,Black,Black,White,0,1,1,1
  1181.     '          |    |     |   |     |     |     |     |     | | | |
  1182.     '          |    |     |   |     |     |     |     |     | | | Shadow: Yes
  1183.     '          |    |     |   |     |     |     |     |     | | Box: Single
  1184.     '          |    |     |   |     |     |     |     |     | Trigger 1st: Yes
  1185.     '          |    |     |   |     |     |     |     |     Imm. trigger: Off
  1186.     '          |    |     |   |     |     |     |     Box background: White
  1187.     '          |    |     |   |     |     |     Box color: Black
  1188.     '          |    |     |   |     |     Highlight background: Black
  1189.     '          |    |     |   |     Highlight text: White
  1190.     '          |    |     |   Hotkey background: White
  1191.     '          |    |     Hotkey text: Red
  1192.     '          |    Item background: White
  1193.     '          Item text: Blue
  1194.   End
  1195. End
  1196.  
  1197.  
  1198. '==================================================================
  1199. ' SUB ShowMsgBox
  1200. '
  1201. ' What it does:
  1202. '   Displays Msg in a custom-sized box.  Appends a space. Awaits
  1203. '   a keystroke, and afterward, "undraws" the box.
  1204. '
  1205. ' Globals affected:
  1206. '   INTEGER BoxWidth
  1207. '   STRING Msg
  1208. '
  1209. ' Other routines called:
  1210. '   GetYN
  1211. '
  1212. '==================================================================
  1213.  
  1214. Sub ShowMsgBox
  1215.   ' Get the length of the string in Msg and write it to BoxWidth, so the
  1216.   ' width of the box can be customized.
  1217.   Put Length Msg into BoxWidth
  1218.   ' Add for padding on left & right, as well as box sides.
  1219.   Put BoxWidth + 6 into BoxWidth
  1220.   ' Make sure box isn't too wide.
  1221.   If BoxWidth > 77 Put 77 into BoxWidth
  1222.   Double Box 2, 2, BoxWidth, 7 Bright White on Black
  1223.   ' Use bright white text on a black background.
  1224.   Text Bright White on Black
  1225.   ' Display the message starting at the left side of the box, leaving a
  1226.   ' space of breathing room.
  1227.   Say @ 5, 4 Msg + " ";
  1228.   ' Await a keypress.
  1229.   GetKey
  1230.   ' Redraw over the box.
  1231.   RedrawMsgArea
  1232. End ' Sub GetYNMessage
  1233.  
  1234. '==================================================================
  1235. ' SUB ValidateDrive
  1236. '
  1237. ' What it does:
  1238. '   Ensures the string DriveSpec contains a single letter.
  1239. '   Sets CorrectParams to 1 if the drive is valid, 0 if not.
  1240. '   If the drive is invalid, prints an error message.
  1241. '
  1242. ' Globals affected:
  1243. '   INTEGER CorrectParams, MsgLen
  1244. '   STRING DriveSpec
  1245. '
  1246. '==================================================================
  1247.  
  1248. Sub ValidateDrive
  1249.   ' Assume DriveSpec is invalid.
  1250.   Put 0 into CorrectParams
  1251.   ' Now we have a source and a target drive. Validate them:
  1252.   If not (DriveSpec contains ":")
  1253.     ' Make sure there's only 1 letter in the drive specification.
  1254.     Put Length DriveSpec into MsgLen
  1255.     ' If it's a single letter, everything's cool.
  1256.     If MsgLen is 1 CorrectParams := 1
  1257.   End ' If not
  1258.  End ' Sub ValidateDrive
  1259.  
  1260.  
  1261.  
  1262. '==================================================================
  1263. ' SUB CopyFiles
  1264. '
  1265. ' What it does:
  1266. '   Checks source and target drives, then copies the installation
  1267. '   data file (which contains the list of filenames) to the
  1268. '   target directory.  After that, begins the actual
  1269. '   process of copying files from the source floppy to the
  1270. '   target directory.  Closes InFile when finished.
  1271. '
  1272. '   Appends colon to SourceDrive, turning it, for example, into
  1273. '   "A:" from "A".  Same with TargetDrive.
  1274. '
  1275. '   Returns:
  1276. '     0 in BothDrives if one of the drives isn't ready
  1277. '
  1278. '   At this point we know:
  1279. '   * The target directory is available or has been created.
  1280. '   * The source and target drives are ready.
  1281. '
  1282. ' Globals affected:
  1283. '   FILE InFile
  1284. '   INTEGER BothReady, IsDescription
  1285. '   STRING CorrectDrive, CorrectLabel, DiskStatus, DriveSpec,
  1286. '          InstName, NextLine, SourceDrive, TargetDrive
  1287. '
  1288. ' Other routines called:
  1289. '   CheckDrives, CorrectDrive, ErrMsg
  1290. '
  1291. '==================================================================
  1292.  
  1293. Sub Copyfiles
  1294.   ' Disable hardware text cursor.
  1295.   Don't use cursor
  1296.   ' Ensure both source and target drives are ready.
  1297.   ' Print an error message and quit this routine if either drive isn't
  1298.   ' ready.
  1299.   If BothReady is 0
  1300.     Put "Both drives must be working to install." into Msg
  1301.     ErrMsg
  1302.   end else
  1303.     If BothReady is 0
  1304.       'Put "Please insert the disk labeled " + CorrectLabel into Msg
  1305.       'ErrMsg
  1306.     end else
  1307.       ' Make SourceDrive and TargetDrive real drive specs by
  1308.       ' appending colons.
  1309.       SourceDrive := SourceDrive + ":"
  1310.       TargetDrive := TargetDrive + ":"
  1311.       ' Copy the installation file to the target drive.
  1312.       System "Copy " + SourceDrive + InstName + " " + Target + " > nul"
  1313.       ' Change to the target drive and directory.
  1314.       System TargetDrive
  1315.       System "CD " + Target
  1316.       ' DiskStatus is 0 if there's a problem.
  1317.       Put 1 into DiskStatus
  1318.       ' Make sure the install file got copied correctly.
  1319.       Open InstName for Reading as Infile
  1320.       ' Create a file to be written as files are copied.
  1321.       Open CheckName for Writing as CheckFile
  1322.       ' Write a header to that file.
  1323.       WriteLine "Files missing from " + Target to CheckFile
  1324.       Double Box 17, 7, 68, 9 White on Black
  1325.       Text Bright White on black
  1326.       say @ 18, 9 "<bold>Now copying files. Press {Space} to pause or {Esc} to quit."
  1327.       say @ 21, 9 "Copying file <bold>"; NextLine; " to <bold>"; Target
  1328.       say @ 22, 9 "DOS messages: ";
  1329.       ' Continue only if everything's okay.
  1330.       If DiskStatus is 1
  1331.         While Not EOF InFile
  1332.           ' Copy the next line of the file into the variable NextLine.
  1333.           ' Ignore comment lines in the data file.
  1334.           GetNextLine
  1335.           ' If it's a description line (we know because the line contains
  1336.           ' the <bold> metacharacter), display it verbatim.  This lets us
  1337.           ' identify the file being copied.
  1338.           if IsDescription
  1339.             ' Blank out the previous description.
  1340.             say @ 20, 9 "                                              "
  1341.             ' Display this description.
  1342.             say @ 20, 9 NextLine
  1343.             ' Get the next line, which MUST be a filename.
  1344.             ' Ignore comment lines in the data file.
  1345.              GetNextLine
  1346.           end
  1347.  
  1348.           ' Copy this if it's a valid filespec.  Don't copy if it's a
  1349.           ' description or comment line.
  1350.           If ShouldCopy is 1
  1351.             ' Let the user halt the copy procedure.
  1352.             CheckPause
  1353.             ' Undraw any previous text drawn on this line.
  1354.             say @ 21, 21 "                                              "
  1355.             ' Display the name of the next file to be copied in boldface.
  1356.             say @ 21, 21 " <bold>"; NextLine; " to <bold>"; Target
  1357.              ' Copy the file to the target drive.
  1358.             RowCol 22, 22
  1359.             System "Copy " + SourceDrive + NextLine + "/B " + TargetDrive + " /B /V > nul"
  1360.             ' We know that at least 1 file made it.
  1361.             InstallError := 1
  1362.             ' Track the filename that was copied.
  1363.             ' Build up a name consisting of the target directory and the
  1364.             ' filename.
  1365.             TargetFile := Target + "\" + NextLine
  1366.             ' If the file wasn't copied over, increment the counter of # of
  1367.             ' files that didn't make it.
  1368.             DiskStatus := 0
  1369.             If Not exist TargetFile DiskStatus := 1
  1370.             ' If file wasn't copied over, write
  1371.             If DiskStatus is 1
  1372.               ' Track the # of files not found.
  1373.               Missing := Missing + 1
  1374.               ' Copy its name to a list of missing files.
  1375.               WriteLine NextLine to CheckFile
  1376.             end
  1377.               ' No files missing.
  1378.               Put 2 into InstallError
  1379.             End
  1380.         End ' While Not EOF
  1381.       End ' If DiskStatus
  1382.     End ' If BothReady is 0
  1383.   End ' If BothReady is 0
  1384.   ' Restore the hardware text cursor.
  1385.   Use cursor
  1386.   ' Return all file resources to DOS.
  1387.   CloseAllFiles
  1388. End ' Sub Copyfiles.
  1389.  
  1390. '==================================================================
  1391. '
  1392. ' SUB SayGoodBye
  1393. '
  1394. ' 4. SIGN OFF
  1395. '    Replace the message in this routine with your own, or rewrite
  1396. '    it completely.
  1397. '
  1398. ' What it does:
  1399. '   Displays a sign-off message.
  1400. '
  1401. '
  1402. ' Globals affected:
  1403. '   INTEGER BoxWidth
  1404. '   STRING Msg
  1405. '
  1406. ' Other routines called:
  1407. '   GetYN
  1408. '
  1409. '==================================================================
  1410. Sub SayGoodBye
  1411.   ' Put a white on on blue banner across the top.
  1412.   Text White on Blue
  1413.   ' Draw a bar across the top.
  1414.   Repeat 79
  1415.     Say "▓";
  1416.   End
  1417.   ' Thank the user.
  1418.   say @ 1, 25 "Thank you for using The Builder"
  1419. End ' Sub SayGoodBye
  1420.  
  1421. '==================================================================
  1422. ' SUB DoInstall
  1423. '
  1424. ' What it does:
  1425. '   Performs the actual installation, either full or minimal.
  1426. '   Assumes the installation data file exists.
  1427. '
  1428. ' Globals affected:
  1429. '   INTEGER BothReady
  1430. '   STRING DefFullFile, DiskStatus, InstName
  1431. '
  1432. ' Other routines called:
  1433. '   CheckDrives, CopyFiles, CreateDirectories, ErrMsg,
  1434. '   GetAndConfirmParams
  1435. '
  1436. '==================================================================
  1437. Sub DoInstall
  1438.  
  1439.   ' Filename for the CopyFiles routine.
  1440.   Copying:=1
  1441.   if FullInstall == 1
  1442.   InstName := DefFullFile
  1443.   end else
  1444.   InstName := DefMinFile
  1445.   end
  1446.   
  1447.   DiskStatus:=DiskReady SourceDrive
  1448.   if DiskStatus<>0
  1449.   If exist SourceDrive+":"+InstName DiskStatus:=1
  1450.   end
  1451.   If DiskStatus
  1452.     GetAndConfirmParams
  1453.     ' Make sure the specified drives are acceptable.
  1454.     CheckDrives
  1455.     If BothReady <> 0
  1456.        DiskStatus := 0
  1457.       CreateDirectories
  1458.       if DiskStatus <> 0
  1459.         CopyFiles
  1460.       end else
  1461.         Msg := "Can't create the subdirectory " + Target
  1462.         ErrMsg
  1463.       end ' If DiskStatus
  1464.     End ' If BothReady
  1465.   end else
  1466.     Msg := "Can't find the installation file " + InstName
  1467.     ErrMsg
  1468.   End ' If DiskStatus
  1469.  Copying:=0
  1470. End ' Sub DoInstall
  1471.  
  1472. '==================================================================
  1473. ' SUB MakeDir
  1474. '
  1475. ' What it does:
  1476. '   Responds to a "MAKE_TARGET_DIR" line.  Expects that the next line
  1477. '   will be a subdirectory name. If that subdirectory doesn't
  1478. '   already exist, creates it and changes to that target directory.
  1479. '   Reassigns TargetDir to that new directory.
  1480. '
  1481. '   IMPORTANT NOTE:  Assumes that this is one level down from the
  1482. '   current target directory (which may have been created using
  1483. '   a previous MAKE_TARGET_DIR).  So if TargetDir is C:\BUILDER, and
  1484. '   this line is EXAMPLES, the directory C:\BUILDER\EXAMPLES is
  1485. '   created.
  1486. '
  1487. ' Globals affected:
  1488. '   INTEGER DiskStatus, NextLine
  1489. '   STRING NextLine, TargetDir
  1490. '
  1491. ' Other routines called:
  1492. '   GetNextLine
  1493. '
  1494. '==================================================================
  1495.  
  1496.  
  1497. Sub MakeDir
  1498.   ' Get the next non-comment line from the disk and copy to the
  1499.   ' variable NextLine.
  1500.   GetNextLine
  1501.   ' NextLine now has the subdir name to check for and create (if necessary).
  1502.   ' See if it already exists.  DiskStatus will be 1 if it does.
  1503.   DiskStatus := DirExists NextLine
  1504.   If DiskStatus is 0
  1505.     ' Doesn't exist. Change to it and create it.
  1506.     ' Change to the target directory. (Actually, we should already be there.)
  1507.     System "CD " + TargetDrive + TargetDir
  1508.     ' Create it.
  1509.     Msg := "About to: " + "MD " + TargetDrive + TargetDir + "\" + NextLine + ", press return."
  1510.     ShowMsgBox
  1511.     System "MD " + TargetDrive + TargetDir + "\" + NextLine
  1512.     TargetDir := TargetDir + "\" + NextLine
  1513.   end
  1514.   ' Change to the new directory.
  1515.   System "CD " + TargetDrive + TargetDir
  1516. End ' Sub MakeDir
  1517.  
  1518. '==================================================================
  1519. ' SUB ChangeDir
  1520. '
  1521. ' What it does:
  1522. '   Responds to a "CHANGE_TARGET_DIR" line.  Expects that the next
  1523. '   line will be a subdirectory name. Changes to that target
  1524. '   directory,  and reassigns TargetDir to that new directory.
  1525. '
  1526. '   NOTE: Doesn't change the logged disk drive, and inserts the
  1527. '         target drive spec before it.
  1528. '
  1529. ' Globals affected:
  1530. '   STRING NextLine, TargetDir
  1531. '
  1532. ' Other routines called:
  1533. '   GetNextLine
  1534. '
  1535. '==================================================================
  1536. Sub ChangeDir
  1537.   ' Get the next non-comment line from the disk and copy to the
  1538.   ' variable NextLine.
  1539.   GetNextLine
  1540.   ' NextLine now has the subdir name to change to.
  1541.   ' Change to the target directory. (Actually, we should already be there.)
  1542.   System "CD " + TargetDrive + NextLine
  1543.   ' Make this the new target directory.
  1544.   TargetDir := NextLine
  1545. End ' Sub ChangeDir
  1546.  
  1547. '==================================================================
  1548. ' SUB RedrawMsgArea
  1549. '
  1550. ' What it does:
  1551. '   Writes over the message window in the current screen color
  1552. '   and regenerates the title, so that the display looks as it
  1553. '   did before the message window was drawn.
  1554. '
  1555. ' Globals affected:
  1556. '   INTEGER BoxWidth
  1557. '   STRING ScreenWidth
  1558. '
  1559. ' Other routines called:
  1560. '   None
  1561. '
  1562. '==================================================================
  1563.  
  1564. SUB RedrawMsgArea
  1565.   ' Redraw over the box.
  1566.   if ScreenType is "Mono"
  1567.     Double Box 2, 2, BoxWidth, 7 Black on Black
  1568.   end else
  1569.     Double Box 2, 2, BoxWidth, 7 Blue on Blue
  1570.   end
  1571.   ' Display a banner.
  1572.   Text white on Blue
  1573.   Say @ 2, 23 "<bold>Builder 1.50 installation program"
  1574.   if Copying==0
  1575.   Say @ 20, 10 "Press <bold><reverse><normal> and <bold><reverse><normal> ";
  1576.   Say "to move the cursor and press {Enter} to select.";
  1577.   end
  1578. End ' SUB RedrawMsgArea
  1579.  
  1580. '==================================================================
  1581. ' SUB Extraction
  1582. '
  1583. ' What it does:
  1584. '   Responds to a "RUN_EXTRACTION" line.  Expects that the next lines
  1585. '   will be a filename, directory then a prompt.  Displays the prompt,
  1586. '   then extracts the filename.
  1587. '
  1588. ' Globals affected:
  1589. '   STRING Msg, NextLine, Scratch1, Correctlabel
  1590. '
  1591. ' Other routines called:
  1592. '   GetNextLine
  1593. '
  1594. '==================================================================
  1595.  
  1596. Sub Extraction
  1597.   ' Get the next non-comment line from the disk and copy to the
  1598.   ' variable NextLine.
  1599.   GetNextLine
  1600.   ' This is the filename to extract.
  1601.   CorrectLabel := NextLine
  1602.   ' Get the next non-comment line from the disk and copy to the
  1603.   ' variable DiskPrompt.
  1604.   GetNextLine
  1605.   'This is the directory to extract to.
  1606.   scratch1:=NextLine
  1607.   GetNextLine
  1608.   ' This is the prompt to display.
  1609.   MSG := NextLine
  1610.   'This commandline will extract the Lharc selfextracting archive
  1611.   System SourceDrive+CorrectLabel+" /e"+Target+Scratch1+" >nul"
  1612.  
  1613. End ' Sub Extraction
  1614.  
  1615.  
  1616.