1 ////////////////////////////////////////////////////////////////////////////////
4 // II SS InstallShield (R)
5 // II SSSSSS (c) 1996-1997, InstallShield Software Corporation
6 // II SS (c) 1990-1996, InstallShield Corporation
7 // IIIIIII SSSSSS All Rights Reserved.
10 // This code is generated as a starting setup template. You should
11 // modify it to provide all necessary steps for your setup.
14 // File Name: Setup.rul
16 // Description: InstallShield script
18 // Comments: This template script performs a basic setup on a
19 // Windows 95 or Windows NT 4.0 platform. With minor
20 // modifications, this template can be adapted to create
21 // new, customized setups.
23 ////////////////////////////////////////////////////////////////////////////////
26 // Include header file
29 ////////////////////// string defines ////////////////////////////
31 #define UNINST_LOGFILE_NAME "Uninst.isu"
33 //////////////////// installation declarations ///////////////////
35 // ----- DLL prototypes -----
38 // your DLL prototypes
41 // ---- script prototypes -----
44 prototype ShowDialogs();
45 prototype MoveFileData();
46 prototype HandleMoveDataError( NUMBER );
47 prototype ProcessBeforeDataMove();
48 prototype ProcessAfterDataMove();
49 prototype SetupRegistry();
50 prototype SetupFolders();
51 prototype CleanUpInstall();
52 prototype SetupInstall();
53 prototype SetupScreen();
54 prototype CheckListScreen();
55 prototype CheckRequirements();
56 prototype DialogShowSdWelcome();
57 prototype DialogShowSdShowInfoList();
58 prototype DialogShowSdAskDestPath();
59 prototype DialogShowSdSetupType();
60 prototype DialogShowSdComponentDialog2();
61 prototype DialogShowSdSelectFolder();
62 prototype DialogShowSdFinishReboot();
65 prototype MyParsePath ( STRING );
66 prototype ForwardSlashify ( STRING, BYREF STRING );
67 prototype CreateExecPerlScript ( STRING, STRING );
68 prototype DropSuffix ( STRING, BYREF STRING );
69 prototype BaseName ( STRING, BYREF STRING );
71 // ----- global variables ------
74 BOOL bWinNT, bIsShellExplorer, bInstallAborted, bIs32BitSetup;
76 STRING svName, svCompany, svSerial;
82 // your global variables
85 STRING szBinDir, szBinDirUnslashed,
86 szLibDir, szLibDirUnslashed,
87 szDataDir, szLibExecDir;
90 ///////////////////////////////////////////////////////////////////////////////
94 // The setup begins here by hiding the visible setup
95 // window. This is done to allow all the titles, images, etc. to
96 // be established before showing the main window. The following
97 // logic then performs the setup in a series of steps.
99 ///////////////////////////////////////////////////////////////////////////////
101 Disable( BACKGROUND );
109 if (ShowDialogs()<0) goto end_install;
111 if (ProcessBeforeDataMove()<0) goto end_install;
113 if (MoveFileData()<0) goto end_install;
115 if (ProcessAfterDataMove()<0) goto end_install;
117 if (SetupRegistry()<0) goto end_install;
119 if (SetupFolders()<0) goto end_install;
127 // If an unrecoverable error occurred, clean up the partial installation.
128 // Otherwise, exit normally.
130 if (bInstallAborted) then
136 ///////////////////////////////////////////////////////////////////////////////
138 // Function: ShowDialogs //
140 // Purpose: This function manages the display and navigation //
141 // the standard dialogs that exist in a setup. //
143 ///////////////////////////////////////////////////////////////////////////////
144 function ShowDialogs()
149 // beginning of dialogs label
152 nResult = DialogShowSdWelcome();
153 if (nResult = BACK) goto Dlg_Start;
156 nResult = DialogShowSdShowInfoList();
157 if (nResult = BACK) goto Dlg_SdWelcome;
160 nResult = DialogShowSdAskDestPath();
161 if (nResult = BACK) goto Dlg_SdShowInfoList;
164 nResult = DialogShowSdSetupType();
165 if (nResult = BACK) goto Dlg_SdAskDestPath;
167 Dlg_SdComponentDialog2:
168 if ((nResult = BACK) && (svSetupType != "Custom") && (svSetupType != "")) then
169 goto Dlg_SdSetupType;
171 nResult = DialogShowSdComponentDialog2();
172 if (nResult = BACK) goto Dlg_SdSetupType;
175 //nResult = DialogShowSdSelectFolder();
176 //if (nResult = BACK) goto Dlg_SdComponentDialog2;
182 ///////////////////////////////////////////////////////////////////////////////
184 // Function: ProcessBeforeDataMove //
186 // Purpose: This function performs any necessary operations prior to the //
187 // actual data move operation. //
189 ///////////////////////////////////////////////////////////////////////////////
190 function ProcessBeforeDataMove()
195 InstallationInfo( @COMPANY_NAME, @PRODUCT_NAME, @PRODUCT_VERSION, @PRODUCT_KEY );
197 svLogFile = UNINST_LOGFILE_NAME;
199 nResult = DeinstallStart( svDir, svLogFile, @UNINST_KEY, 0 );
200 if (nResult < 0) then
201 MessageBox( @ERROR_UNINSTSETUP, WARNING );
204 szAppPath = TARGETDIR; // TODO : if your application .exe is in a subdir of TARGETDIR then add subdir
206 if ((bIs32BitSetup) && (bIsShellExplorer)) then
207 RegDBSetItem( REGDB_APPPATH, szAppPath );
208 RegDBSetItem( REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY );
209 RegDBSetItem( REGDB_UNINSTALL_NAME, @UNINST_DISPLAY_NAME );
211 // TODO : update any items you want to process before moving the data
214 ComponentSetTarget( MEDIA, "<DOCDIR>", TARGETDIR ^ "\\doc" );
219 ///////////////////////////////////////////////////////////////////////////////
221 // Function: MoveFileData //
223 // Purpose: This function handles the data movement for //
226 ///////////////////////////////////////////////////////////////////////////////
227 function MoveFileData()
228 NUMBER nResult, nDisk;
232 SetStatusWindow( 0, "" );
233 Disable( DIALOGCACHE );
235 StatusUpdate( ON, 100 );
236 nResult = ComponentMoveData( MEDIA, nDisk, 0 );
238 HandleMoveDataError( nResult );
247 ///////////////////////////////////////////////////////////////////////////////
249 // Function: HandleMoveDataError //
251 // Purpose: This function handles the error (if any) during the move data //
254 ///////////////////////////////////////////////////////////////////////////////
255 function HandleMoveDataError( nResult )
256 STRING szErrMsg, svComponent , svFileGroup , svFile;
267 ComponentError ( MEDIA , svComponent , svFileGroup , svFile , nResult );
268 szErrMsg = @ERROR_MOVEDATA + "\n\n" +
269 @ERROR_COMPONENT + " " + svComponent + "\n" +
270 @ERROR_FILEGROUP + " " + svFileGroup + "\n" +
271 @ERROR_FILE + " " + svFile;
272 SprintfBox( SEVERE, @TITLE_CAPTIONBAR, szErrMsg, nResult );
273 bInstallAborted = TRUE;
280 ///////////////////////////////////////////////////////////////////////////////
282 // Function: ProcessAfterDataMove //
284 // Purpose: This function performs any necessary operations needed after //
285 // all data has been moved. //
287 ///////////////////////////////////////////////////////////////////////////////
288 function ProcessAfterDataMove()
289 STRING szPath, szGcc, szGccDir;
290 STRING szTemp, szRes, szPathEntry, szDrive;
291 NUMBER nvSize,nvType, nResult, nPos, nSuccess;
295 RegDBSetDefaultRoot ( HKEY_LOCAL_MACHINE );
296 RegDBGetKeyValueEx ( "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment" ,
297 "path" , nvType, szPath , nvSize );
299 // Spin through path looking for perl.exe.
300 // Our task is made considerably harder since the
301 // the free version of InstallShield doesn't support
302 // functions such as StrGetTokens() or ParsePath().
303 // TODO: Convert this back to IS Prof Edn
305 MyParsePath ( szPath );
306 nResult = ListGetFirstString ( listPath, szPathEntry);
307 szPathEntry = ""; szPerlPath="";
308 while ( nResult != END_OF_LIST )
309 if ( FindFile (szPathEntry, "perl.exe", szRes ) = 0 ) then
310 szPerlPath = szPathEntry + "/" + szRes;
311 nResult = END_OF_LIST;
313 nResult = ListGetNextString ( listPath, szPathEntry );
316 if ( StrCompare ( szPerlPath, "" ) = 0 ) then
317 // If not found in global env. block, look in the
318 // user-specific part.
319 RegDBSetDefaultRoot ( HKEY_CURRENT_USER );
320 RegDBGetKeyValueEx ( "Environment", "path", nvType, szPath, nvSize);
321 MyParsePath ( szPath );
322 nResult = ListGetFirstString ( listPath, szPathEntry);
323 szPathEntry = ""; szPerlPath="";
324 while ( nResult != END_OF_LIST )
325 if ( FindFile (szPathEntry, "perl.exe", szRes ) = 0 ) then
326 szPerlPath = szPathEntry + "/" + szRes;
327 nResult = END_OF_LIST;
329 nResult = ListGetNextString ( listPath, szPathEntry );
334 if ( StrCompare ( szPerlPath, "" ) = 0 ) then
335 // Default it to /bin/perl
336 MessageBox ("Unable to find perl in your PATH. Not to worry, this installer includes a version that should be useable." +
337 "When the installer has finished, please copy it from the bin/ directory of the ghc installation to /bin/perl",
339 szPerlPath = "/bin/perl.exe";
341 // strip initial drive spec.
342 GetDir ( szPerlPath, szTemp);
343 ForwardSlashify ( szTemp, szPerlPath );
345 DropSuffix (szPerlPath, szTemp);
348 ListDestroy (listPath);
353 ///////////////////////////////////////////////////////////////////////////////
355 // Function: SetupRegistry //
357 // Purpose: This function makes the registry entries for this setup. //
359 ///////////////////////////////////////////////////////////////////////////////
360 function SetupRegistry()
361 NUMBER nResult,nWays,i;
362 STRING szProjectDir, szProjectVersionDir, szTargetDir;
363 STRING szSyslib, szWay, szSyslibsDir;
364 STRING szLib, szSyslibsKey;
365 //LIST syslib_list, way_list;
368 // TODO : Add all your registry entry keys here
372 nResult = CreateRegistrySet( "" );
374 // By now, we will have had the following Registry
375 // entries generated (see ProcessBeforeDataMove() ):
377 // HK_L_M\Software\Glasgow University\GHC\<version no.>
379 // For GHC, we store and use the install info inside
380 // HK_L_M\Software\Haskell\GHC (== %ROOT%)
382 // So, we perform the following tasks here:
384 // * Checks to see if %ROOT% is defined.
385 // If not, creates it.
386 // * Checks for %ROOT%\Version is defined.
387 // * Create %ROOT%\<version>.
388 // * Create %ROOT%\<version>\libdir
389 // (This key will be given a value later.)
390 // * Create %ROOT%\syslib\ and fill it in
391 // with the syslibs that has been installed.
392 // * %ROOT%\syslib\name\<way>
393 // is added for each kind (e.g., seq, conc)
394 // syslib we're installing.
396 // When we eventually reach the end, the registry
397 // should be ready for use by the installed app.
399 // Check to see if we've already installed
400 // a version of GHC on this box..
401 RegDBSetDefaultRoot ( HKEY_LOCAL_MACHINE );
403 szProjectDir = @HASKELL_REG_ROOT ^ @PRODUCT_NAME;
405 // check whether we've already got the Registry sub-tree we're
406 // about to add to. If not, then we create it
407 // level-by-level, so as to ensure that the uninstaller
408 // can clean up after us.
409 if ( RegDBKeyExist ( @HASKELL_REG_ROOT ) < 0) then
410 RegDBCreateKeyEx (@HASKELL_REG_ROOT, "");
412 if ( RegDBKeyExist ( szProjectDir ) < 0 ) then
413 RegDBCreateKeyEx ( szProjectDir, "");
416 // Note: we overwrite any existing value.
417 RegDBSetKeyValueEx( szProjectDir, "Version", REGDB_STRING,
420 szProjectVersionDir = szProjectDir ^ @PRODUCT_KEY;
422 if ( RegDBKeyExist ( szProjectVersionDir ) < 0) then
423 RegDBCreateKeyEx ( szProjectVersionDir, "");
426 // Here starts the GHC specific part
428 ForwardSlashify (TARGETDIR, szTargetDir);
429 // fill in the all-important path to where the archives
430 // and interface files have been parked.
431 szLibDir = szTargetDir + "/lib";
432 szLibDirUnslashed = TARGETDIR ^ "\\lib";
433 RegDBSetKeyValueEx ( szProjectVersionDir, "libdir", REGDB_STRING,
436 szLibExecDir = szTargetDir + "/lib";
437 RegDBSetKeyValueEx ( szProjectVersionDir, "libexecdir", REGDB_STRING,
440 szBinDir = szTargetDir + "/bin";
441 szBinDirUnslashed = TARGETDIR ^ "\\bin";
442 RegDBSetKeyValueEx ( szProjectVersionDir, "bindir", REGDB_STRING,
449 ///////////////////////////////////////////////////////////////////////////////
451 // Function: SetupFolders
453 // Purpose: This function creates all the folders and shortcuts for the
454 // setup. This includes program groups and items for Windows 3.1.
456 ///////////////////////////////////////////////////////////////////////////////
457 function SetupFolders()
462 // TODO : Add all your folder (program group) along with shortcuts (program items)
465 // CreateProgramFolder, AddFolderIcon....
468 CreateExecPerlScript ( szBinDirUnslashed, "ghc-" + @PRODUCT_VERSION );
469 CreateExecPerlScript ( szBinDirUnslashed, "stat2resid" );
470 CreateExecPerlScript ( szLibDirUnslashed, "hscpp" );
471 CreateExecPerlScript ( szLibDirUnslashed, "mkdependHS" );
473 VarSave (SRCTARGETDIR);
474 SRCDIR = szBinDirUnslashed;
475 TARGETDIR = szBinDirUnslashed;
476 CopyFile( "ghc-" + @PRODUCT_VERSION, "ghc");
477 VarRestore (SRCTARGETDIR);
479 nResult = CreateShellObjects( "" );
484 ///////////////////////////////////////////////////////////////////////////////
486 // Function: CleanUpInstall //
488 // Purpose: This cleans up the setup. Anything that should //
489 // be released or deleted at the end of the setup should //
492 ///////////////////////////////////////////////////////////////////////////////
493 function CleanUpInstall()
497 if (bInstallAborted) then
501 DialogShowSdFinishReboot();
503 if (BATCH_INSTALL) then // ensure locked files are properly written
504 CommitSharedFiles(0);
510 ///////////////////////////////////////////////////////////////////////////////
512 // Function: SetupInstall //
514 // Purpose: This will setup the installation. Any general initialization //
515 // needed for the installation should be performed here. //
517 ///////////////////////////////////////////////////////////////////////////////
518 function SetupInstall()
522 Enable( CORECOMPONENTHANDLING );
524 bInstallAborted = FALSE;
526 GetDisk(WINDIR, svDir);
528 if (bIs32BitSetup) then
529 svDir = svDir + "\\" ^ @PRODUCT_NAME_SHORT ^ @PRODUCT_KEY;
531 // We're (=>ghc) 32 through and through, but for the sake of
533 svDir = svDir + "\\" ^ @PRODUCT_NAME_SHORT ^ @PRODUCT_NAME16;
538 SdProductName( @PRODUCT_NAME );
540 Enable( DIALOGCACHE );
545 ///////////////////////////////////////////////////////////////////////////////
547 // Function: SetupScreen //
549 // Purpose: This function establishes the screen look. This includes //
550 // colors, fonts, and text to be displayed. //
552 ///////////////////////////////////////////////////////////////////////////////
553 function SetupScreen()
556 SetColor ( BACKGROUND, BLUE );
557 Enable( FULLWINDOWMODE );
558 Enable( INDVFILESTATUS );
560 SetTitle( @TITLE_MAIN, 24, WHITE );
562 SetTitle( @TITLE_CAPTIONBAR, 0, BACKGROUNDCAPTION ); // Caption bar text.
564 Enable( BACKGROUND );
569 ///////////////////////////////////////////////////////////////////////////////
571 // Function: CheckRequirements //
573 // Purpose: This function checks all minimum requirements for the //
574 // application being installed. If any fail, then the user //
575 // is informed and the setup is terminated. //
577 ///////////////////////////////////////////////////////////////////////////////
578 function CheckRequirements()
579 NUMBER nvDx, nvDy, nvResult;
585 bIsShellExplorer = FALSE;
587 // Check screen resolution.
588 GetExtents( nvDx, nvDy );
591 MessageBox( @ERROR_VGARESOLUTION, WARNING );
595 // set 'setup' operation mode
596 bIs32BitSetup = TRUE;
597 GetSystemInfo( ISTYPE, nvResult, svResult );
598 if (nvResult = 16) then
599 bIs32BitSetup = FALSE; // running 16-bit setup
600 return 0; // no additional information required
603 // --- 32-bit testing after this point ---
605 // Determine the target system's operating system.
606 GetSystemInfo( OS, nvResult, svResult );
608 if (nvResult = IS_WINDOWSNT) then
609 // Running Windows NT.
612 // Check to see if the shell being used is EXPLORER shell.
613 if (GetSystemInfo( OSMAJOR, nvResult, svResult ) = 0) then
614 if (nvResult >= 4) then
615 bIsShellExplorer = TRUE;
619 elseif (nvResult = IS_WINDOWS95 ) then
620 bIsShellExplorer = TRUE;
627 ///////////////////////////////////////////////////////////////////////////////
629 // Function: DialogShowSdWelcome //
631 // Purpose: This function handles the standard welcome dialog. //
634 ///////////////////////////////////////////////////////////////////////////////
635 function DialogShowSdWelcome()
637 STRING szTitle, szMsg;
642 nResult = SdWelcome( szTitle, szMsg );
647 ///////////////////////////////////////////////////////////////////////////////
649 // Function: DialogShowSdShowInfoList //
651 // Purpose: This function displays the general information list dialog. //
654 ///////////////////////////////////////////////////////////////////////////////
655 function DialogShowSdShowInfoList()
658 STRING szTitle, szMsg, szFile;
661 szFile = SUPPORTDIR ^ "announce";
663 list = ListCreate( STRINGLIST );
664 ListReadFromFile( list, szFile );
667 nResult = SdShowInfoList( szTitle, szMsg, list );
675 ///////////////////////////////////////////////////////////////////////////////
677 // Function: DialogShowSdAskDestPath //
679 // Purpose: This function asks the user for the destination directory. //
681 ///////////////////////////////////////////////////////////////////////////////
682 function DialogShowSdAskDestPath()
684 STRING szTitle, szMsg;
688 szMsg = "WARNING! The path must not contain spaces.";
689 nResult = SdAskDestPath( szTitle, szMsg, svDir, 0 );
697 ///////////////////////////////////////////////////////////////////////////////
699 // Function: DialogShowSdSetupType //
701 // Purpose: This function displays the standard setup type dialog. //
703 ///////////////////////////////////////////////////////////////////////////////
704 function DialogShowSdSetupType()
705 NUMBER nResult, nType;
706 STRING szTitle, szMsg;
717 svSetupType = "Typical";
723 nResult = SetupType( szTitle, szMsg, "", nType, 0 );
727 svSetupType = "Compact";
729 svSetupType = "Typical";
731 svSetupType = "Custom";
738 ///////////////////////////////////////////////////////////////////////////////
740 // Function: DialogShowSdComponentDialog2 //
742 // Purpose: This function displays the custom component dialog. //
745 ///////////////////////////////////////////////////////////////////////////////
746 function DialogShowSdComponentDialog2()
748 STRING szTitle, szMsg;
751 if ((svSetupType != "Custom") && (svSetupType != "")) then
757 nResult = SdComponentDialog2( szTitle, szMsg, svDir, "" );
762 ///////////////////////////////////////////////////////////////////////////////
764 // Function: CheckListScreen //
766 // Purpose: Show a check-list of post-install user actions. //
768 ///////////////////////////////////////////////////////////////////////////////
769 function CheckListScreen()
773 EzDefineDialog("CHECKLIST", "", "", 30001);
777 nCmdValue = WaitOnDialog("CHECKLIST");
780 // Process the Next button.
781 case SD_PBUT_CONTINUE:
783 // Process the Cancel button.
784 case SD_PBUT_EXITSETUP:
786 // Process the close dialog box button.
789 // Process dialog box errors.
791 MessageBox("Internal dialog box error", SEVERE);
795 // Identify the end of dialog box processing.
796 EndDialog("CHECKLIST");
797 // Free the dialog box and list from memory.
798 ReleaseDialog("CHECKLIST");
801 ///////////////////////////////////////////////////////////////////////////////
803 // Function: DialogShowSdFinishReboot //
805 // Purpose: This function will show the last dialog of the product. //
806 // It will allow the user to reboot and/or show some readme text. //
808 ///////////////////////////////////////////////////////////////////////////////
809 function DialogShowSdFinishReboot()
810 NUMBER nResult, nDefOptions;
811 STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;
815 if (!BATCH_INSTALL) then
822 szTitle = "Installation is now complete.";
823 nResult = SdFinish( szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2 );
826 nDefOptions = SYS_BOOTMACHINE;
830 nResult = SdFinishReboot( szTitle, szMsg1, nDefOptions, szMsg2, 0 );
835 function MyParsePath(szPath)
840 listPath = ListCreate( STRINGLIST );
842 // Man, all I want is map. Please? :-)
843 nPos = StrFind ( szPth, ";");
845 StrSub ( szTmp, szPth, 0, nPos);
846 ListAddString ( listPath, szTmp, AFTER );
847 StrSub ( szTmp, szPth, nPos + 1, StrLength ( szPth) - nPos );
849 nPos = StrFind ( szPth, ";" );
855 function ForwardSlashify ( szStr , theRes )
857 STRING szTemp, szRes;
859 // Tortuous piece of code to convert backslashes into
861 nPos = StrFind ( szStr, "\\");
864 StrSub ( szTemp, szStr, 0, nPos);
865 szRes = szRes + szTemp + "/";
866 StrSub ( szTemp, szStr, nPos + 1, StrLength ( szStr) - nPos );
868 nPos = StrFind ( szStr, "\\" );
870 StrSub ( szTemp, szStr, 0, StrLength (szStr));
871 szRes = szRes + szTemp;
876 function CreateExecPerlScript ( szPath, szFileName )
877 NUMBER nResult, writeHandle, readHandle;
880 VarSave (SRCTARGETDIR);
883 DeleteFile ( szFileName + ".bak");
884 RenameFile ( szFileName, szFileName + ".bak");
885 VarRestore (SRCTARGETDIR);
887 OpenFileMode (FILE_MODE_APPEND);
888 if ( CreateFile ( writeHandle, szPath, szFileName ) < 0 ) then
889 MessageBox ("CreateFile " + szPath ^ szFileName + " failed", INFORMATION);
892 WriteLine (writeHandle, "#!" + szPerlPath );
893 WriteLine (writeHandle, "$libdir='" + szLibDir + "';");
894 WriteLine (writeHandle, "$bindir='" + szBinDir + "';");
895 WriteLine (writeHandle, "$libexecdir='" + szLibExecDir + "';");
896 WriteLine (writeHandle, "$datadir='" + szDataDir + "';");
897 WriteLine (writeHandle, "$SED='sed';");
898 WriteLine (writeHandle, "$TMPDIR='C:/TEMP';");
899 WriteLine (writeHandle, "$RAWCPP='gcc -E';");
900 // For the benefit of mkdependHS, which doesn't get this prepended
901 WriteLine (writeHandle, "$INSTALLING=1;");
903 OpenFileMode (FILE_MODE_NORMAL);
904 if ( OpenFile ( readHandle, szPath, szFileName + ".bak") < 0 ) then
905 MessageBox ("OpenFile " + szPath ^ szFileName + ".bak failed", INFORMATION);
908 // copy the template over.
909 nResult = GetLine ( readHandle, szLine);
910 while ( nResult >= 0 )
911 WriteLine ( writeHandle, szLine);
912 nResult = GetLine ( readHandle, szLine);
914 if ( CloseFile( readHandle ) < 0 ) then
915 MessageBox ( "CloseFile " + szPath ^ szFileName + ".bak failed",
918 if ( CloseFile( writeHandle ) < 0 ) then
919 MessageBox ( "CloseFile " + szPath ^ szFileName + " failed",
922 // There's no way to set the 'x' bit using
923 // SetFileInfo(), but luckily it is not needed to run #! scripts
925 SetFileInfo ( szPath ^ szFileName, FILE_ATTRIBUTE, FILE_ATTR_NORMAL, "");
926 // Delete the .bak file
927 DeleteFile ( szPath ^ szFileName + ".bak");
932 function DropSuffix ( szInp, szOut )
933 NUMBER nResult, nLen;
934 STRING szTemp, szTemp2;
938 nResult = StrFind ( szTemp2 , ".");
939 while ( nResult >= 0 )
940 nLen = nLen + nResult;
941 StrSub ( szTemp, szTemp2, nResult + 1, StrLength ( szTemp2) - nResult );
943 nResult = StrFind ( szTemp2, "." );
944 if ( nResult >= 0 ) then
945 nLen = nLen + 1; // incl the previous . if there's more.
948 StrSub ( szOut, szInp, 0, nLen);