diff --git a/Contrib/InstallOptions/Install Options.html b/Contrib/InstallOptions/Install Options.html index dfc8b1f4..74174246 100644 --- a/Contrib/InstallOptions/Install Options.html +++ b/Contrib/InstallOptions/Install Options.html @@ -82,9 +82,9 @@ following values: (optional) Controls whether or not the cancel button in the NSIS window is shown. If set to 1 or omitted, the cancel button will be shown. If set to 0, the cancel button will be hidden. - BackEnabled + BackDisabled (optional) - Controls whether or not the back button in the NSIS window is enabled. If set to 0 or omitted, the back button will be disabled. If set to 1, the back button will be enabled. + Controls whether or not the back button in the NSIS window is disabled. If set to 0 or omitted, the back button will be enabled. If set to 1, the back button will be disabled. CancelButtonText (optional) diff --git a/Contrib/InstallOptions/InstallerOptions.cpp b/Contrib/InstallOptions/InstallerOptions.cpp index a41042dc..9e1ad209 100644 --- a/Contrib/InstallOptions/InstallerOptions.cpp +++ b/Contrib/InstallOptions/InstallerOptions.cpp @@ -44,6 +44,8 @@ * * - Added Icon and Bitmap controls (by Amir Szekely 4th September 2002) * + * - Added initDialog and show for support with NSIS's new CreateFont and SetStaticBkColor + * * Copyright (C) 2001 Michael Bishop * Portions Copyright (C) 2001 Nullsoft, Inc. * @@ -166,7 +168,7 @@ char *pszCancelButtonText = NULL; char *pszNextButtonText = NULL; char *pszBackButtonText = NULL; unsigned int nCancelConfirmFlags=0; -BOOL bBackEnabled=FALSE; +BOOL bBackDisabled=FALSE; BOOL bCancelEnabled=TRUE; // by ORTIM: 13-August-2002 int bCancelShow=1; // by ORTIM: 13-August-2002 @@ -309,7 +311,7 @@ bool ValidateFields() { // this if statement prevents a stupid bug where a min/max length is assigned to a label control // where the user obviously has no way of changing what is displayed. (can you say, "infinite loop"?) if (pFields[nIdx].nType >= FIELD_TEXT) { - nLength = GetWindowTextLength(pFields[nIdx].hwnd); + nLength = SendMessage(pFields[nIdx].hwnd, WM_GETTEXTLENGTH, 0, 0); if (((pFields[nIdx].nMaxLength > 0) && (nLength > pFields[nIdx].nMaxLength)) || ((pFields[nIdx].nMinLength > 0) && (nLength < pFields[nIdx].nMinLength))) { @@ -374,7 +376,7 @@ bool SaveSettings(void) { } default: { - int nLength = GetWindowTextLength(pFields[nIdx].hwnd); + int nLength = SendMessage(pFields[nIdx].hwnd, WM_GETTEXTLENGTH, 0, 0); if (nLength > nBufLen) { FREE(pszBuffer); // add a bit extra so we do this less often @@ -481,7 +483,7 @@ bool ReadSettings(void) { nCancelConfirmFlags = LookupTokens(MBFlagTable, szResult); nNumFields = GetPrivateProfileInt("Settings", "NumFields", 0, pszFilename); - bBackEnabled = GetPrivateProfileInt("Settings", "BackEnabled", 0, pszFilename); + bBackDisabled = GetPrivateProfileInt("Settings", "BackDisabled", 0, pszFilename); bCancelEnabled = GetPrivateProfileInt("Settings", "CancelEnabled", 1, pszFilename); // by ORTIM: 13-August-2002 bCancelShow = GetPrivateProfileInt("Settings", "CancelShow", 1, pszFilename); // by ORTIM: 13-August-2002 @@ -702,66 +704,76 @@ BOOL CALLBACK cfgDlgProc(HWND hwndDlg, } } break; + case WM_CTLCOLORSTATIC: + { + COLORREF color = GetWindowLong((HWND)lParam, GWL_USERDATA); + if (color) { + LOGBRUSH b={BS_SOLID, color-1, 0}; + SetBkColor((HDC)wParam, b.lbColor); + return (BOOL)CreateBrushIndirect(&b); + } + } } return 0; } +int nIdx; +HWND childwnd; +int cw_vis; +int was_cancel_enabled; +int was_ok_enabled; +char old_cancel[256]; +char old_ok[256]; +char old_back[256]; +int old_cancel_enabled; +int old_cancel_visible; +char old_title[1024]; - - -extern "C" void __declspec(dllexport) dialog(HWND hwndParent, int string_size, - char *variables, stack_t **stacktop) +int createCfgDlg() { - hMainWindow=hwndParent; - EXDLL_INIT(); - - int nIdx; UINT nAddMsg; + g_is_back=0; + g_is_cancel=0; + if (!hMainWindow) { popstring(NULL); pushstring("error finding mainwnd"); - return; // cannot be used in silent mode unfortunately. + return 1; // cannot be used in silent mode unfortunately. } - HWND childwnd=FindWindowEx(hMainWindow,NULL,"#32770",NULL); // find window to replace + childwnd=FindWindowEx(hMainWindow,NULL,"#32770",NULL); // find window to replace if (!childwnd) childwnd=GetDlgItem(hMainWindow,1018); if (!childwnd) { popstring(NULL); pushstring("error finding childwnd"); - return; + return 1; } - if (!stacktop || !*stacktop || !(pszFilename = (*stacktop)->text) || !pszFilename[0] || !ReadSettings()) + if (!g_stacktop || !*g_stacktop || !(pszFilename = (*g_stacktop)->text) || !pszFilename[0] || !ReadSettings()) { popstring(NULL); pushstring("error finding config"); - return; + return 1; } - int cw_vis=IsWindowVisible(childwnd); + cw_vis=IsWindowVisible(childwnd); if (cw_vis) ShowWindow(childwnd,SW_HIDE); - int was_cancel_enabled=EnableWindow(GetDlgItem(hMainWindow,IDCANCEL),1); - int was_ok_enabled=EnableWindow(GetDlgItem(hMainWindow,IDOK),1); - static char old_cancel[256]; + was_cancel_enabled=EnableWindow(GetDlgItem(hMainWindow,IDCANCEL),1); + was_ok_enabled=EnableWindow(GetDlgItem(hMainWindow,IDOK),1); GetDlgItemText(hMainWindow,IDCANCEL,old_cancel,sizeof(old_cancel)); if (pszCancelButtonText) SetDlgItemText(hMainWindow,IDCANCEL,pszCancelButtonText); - static char old_ok[256]; GetDlgItemText(hMainWindow,IDOK,old_ok,sizeof(old_ok)); if (pszNextButtonText) SetDlgItemText(hMainWindow,IDOK,pszNextButtonText); - static char old_back[256]; GetDlgItemText(hMainWindow,3,old_back,sizeof(old_back)); if (pszBackButtonText) SetDlgItemText(hMainWindow,3,pszBackButtonText); - int old_back_enabled=!EnableWindow(GetDlgItem(hMainWindow,3),bBackEnabled); - int old_back_visible=IsWindowVisible(GetDlgItem(hMainWindow,3)); - ShowWindow(GetDlgItem(hMainWindow,3),bBackEnabled?SW_SHOWNA:SW_HIDE); + EnableWindow(GetDlgItem(hMainWindow,3),!bBackDisabled); - - int old_cancel_enabled=!EnableWindow(GetDlgItem(hMainWindow,IDCANCEL),bCancelEnabled); // by ORTIM: 13-August-2002 - int old_cancel_visible=IsWindowVisible(GetDlgItem(hMainWindow,IDCANCEL)); // by ORTIM: 13-August-2002 + old_cancel_enabled=!EnableWindow(GetDlgItem(hMainWindow,IDCANCEL),bCancelEnabled); // by ORTIM: 13-August-2002 + old_cancel_visible=IsWindowVisible(GetDlgItem(hMainWindow,IDCANCEL)); // by ORTIM: 13-August-2002 EnableWindow(GetDlgItem(hMainWindow,IDCANCEL),bCancelEnabled?SW_SHOWNA:SW_HIDE); // by ORTIM: 13-August-2002 ShowWindow(GetDlgItem(hMainWindow,IDCANCEL),bCancelShow?SW_SHOWNA:SW_HIDE); // by ORTIM: 13-August-2002 @@ -786,7 +798,7 @@ extern "C" void __declspec(dllexport) dialog(HWND hwndParent, int string_size, { popstring(NULL); pushstring("error creating dialog"); - return; + return 1; } // by ORTIM: 14-August-2002 @@ -972,16 +984,24 @@ extern "C" void __declspec(dllexport) dialog(HWND hwndParent, int string_size, } } - static char old_title[1024]; if (pszTitle) { GetWindowText(hMainWindow,old_title,sizeof(old_title)); SetWindowText(hMainWindow,pszTitle); } + char tmp[32]; + wsprintf(tmp,"%d",hConfigWindow); + pushstring(tmp); + return 0; +} +void showCfgDlg() +{ ShowWindow(hConfigWindow, SW_SHOWNA); SetFocus(GetDlgItem(hMainWindow,IDOK)); + g_done=0; + while (!g_done) { MSG msg; int nResult = GetMessage(&msg, NULL, 0, 0); @@ -1002,12 +1022,9 @@ extern "C" void __declspec(dllexport) dialog(HWND hwndParent, int string_size, SetDlgItemText(hMainWindow,IDOK,old_ok); SetDlgItemText(hMainWindow,3,old_back); - EnableWindow(GetDlgItem(hMainWindow,3),old_back_enabled); - EnableWindow(GetDlgItem(hMainWindow,IDCANCEL),old_cancel_enabled); // by ORTIM: 13-August-2002 ShowWindow(GetDlgItem(hMainWindow,IDCANCEL),old_cancel_visible?SW_SHOWNA:SW_HIDE); // by ORTIM: 13-August-2002 - ShowWindow(GetDlgItem(hMainWindow,3),old_back_visible?SW_SHOWNA:SW_HIDE); if (pszTitle) SetWindowText(hMainWindow,old_title); if (cw_vis) ShowWindow(childwnd,SW_SHOWNA); @@ -1031,7 +1048,48 @@ extern "C" void __declspec(dllexport) dialog(HWND hwndParent, int string_size, pushstring(g_is_cancel?"cancel":g_is_back?"back":"success"); } +int initCalled; +extern "C" void __declspec(dllexport) dialog(HWND hwndParent, int string_size, + char *variables, stack_t **stacktop) +{ + hMainWindow=hwndParent; + EXDLL_INIT(); + if (initCalled) { + pushstring("error"); + return; + } + if (createCfgDlg()) { + return; + } + popstring(NULL); + showCfgDlg(); +} + +extern "C" void __declspec(dllexport) initDialog(HWND hwndParent, int string_size, + char *variables, stack_t **stacktop) +{ + hMainWindow=hwndParent; + EXDLL_INIT(); + if (initCalled) { + pushstring("error"); + return; + } + initCalled++; + createCfgDlg(); +} + +extern "C" void __declspec(dllexport) show(HWND hwndParent, int string_size, + char *variables, stack_t **stacktop) +{ + EXDLL_INIT(); + if (!initCalled) { + pushstring("error"); + return; + } + initCalled--; + showCfgDlg(); +} extern "C" BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) { diff --git a/Contrib/InstallOptions/io.dsp b/Contrib/InstallOptions/io.dsp index c703fe59..36d6a4c7 100644 --- a/Contrib/InstallOptions/io.dsp +++ b/Contrib/InstallOptions/io.dsp @@ -43,7 +43,8 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTOPTDLL_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTOPTDLL_EXPORTS" /D "WIN32_LEAN_AND_MEAN" /YX /FD /c +# ADD CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTOPTDLL_EXPORTS" /D "WIN32_LEAN_AND_MEAN" /FD /c +# SUBTRACT CPP /FA /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" diff --git a/Docs/src/attributes.but b/Docs/src/attributes.but index d570c363..d30ca262 100644 --- a/Docs/src/attributes.but +++ b/Docs/src/attributes.but @@ -14,7 +14,7 @@ Adds a branding image on the top of the installer or on the left. Its size will \c true|\\false\\ -Controls whether or not installs are enabled to the root directory of a drive, or directly into a network share. Set to 'true' to change the safe behavior, which prevents users from selecting C:\\ or \\\\Server\\Share as an install (and later on, uninstall) directory. For additional directory selection page customizability, see .onVerifyInstDir (\k{onVerifyInstDir}). +Controls whether or not installs are enabled to the root directory of a drive, or directly into a network share. Set to 'true' to change the safe behavior, which prevents users from selecting C:\\ or \\\\Server\\Share as an install (and later on, uninstall) directory. For additional directory selection page customizability, see .onVerifyInstDir (\k{onverifyinstdir}). \H{aautoclosewindow} AutoCloseWindow diff --git a/Docs/src/build.bat b/Docs/src/build.bat index b9dd6af7..c7ee128d 100644 --- a/Docs/src/build.bat +++ b/Docs/src/build.bat @@ -1,4 +1,4 @@ -bin\halibut.exe config.but intro.but usage.but script.but attributes.but compilerflags.but sections.but basic.but registry.but generalpurpose.but flowcontrol.but file.but misc.but string.but stack.but int.but reboot.but uninstall.but log.but sec.but functions.but labels.but var.but usection.but callback.but compiler.but defines.but plugin.but history.but modernui.but usefulfunc.but license.but +bin\halibut.exe config.but intro.but usage.but script.but attributes.but compilerflags.but pages.but sections.but basic.but registry.but generalpurpose.but flowcontrol.but file.but misc.but string.but stack.but int.but reboot.but uninstall.but log.but sec.but functions.but labels.but var.but usection.but callback.but compiler.but defines.but plugin.but history.but modernui.but usefulfunc.but license.but @del *.hlp @del *.cnt @copy Contents.html index.html diff --git a/Docs/src/callback.but b/Docs/src/callback.but index 1e773fc5..6c07ab87 100644 --- a/Docs/src/callback.but +++ b/Docs/src/callback.but @@ -4,6 +4,22 @@ You can create callback functions which have special names, that will be called \H{instcallbacks} Install Callbacks +\S{onguiinit} .onGUIInit + +This callback will be called just before the first page is loaded and the installer dialog is shown, allowing you to tweak the the user interface. + +Example: + +\c !insertmacro ${NSISDIR}\Examples\WinMessages.NSH +\c +\c Funciton .onGUIInit +\c # 1028 is the id of the branding text control +\c GetDlgItem $R0 $HWNDPARENT 1028 +\c CreateFont $R1 "Tahoma" 10 700 +\c SendMessage $R0 ${WM_SETFONT} $R1 0 +\c SetStaticBkColor $R0 0x00FFFFFF +\c FunctionEnd + \S{oninit} .onInit This callback will be called when the installer is nearly finished initializing. If the '.onInit' function calls Abort, the installer will quit instantly. @@ -26,11 +42,7 @@ or: \c NoAbort: \c FunctionEnd -\S{oninitdialog} .onInitDialog - -This callback is called right after an inner dialog is created (excluding InstallOptions dialogs) and before it is shown. Useful for CreateFont, SetStaticBkColor and any other last minute text changes. - -\S{onInstFailed} .onInstFailed +\S{oninstfailed} .onInstFailed This callback is called when the user hits the 'cancel' button after the install has failed (if it could not extract a file, or the install script used the Abort command). @@ -40,7 +52,7 @@ Example: \c MessageBox MB_OK "Better luck next time." \c FunctionEnd -\S{onInstSuccess} .onInstSuccess +\S{oninstsuccess} .onInstSuccess This callback is called when the install was successful, right before the install window closes (which may be after the user clicks 'Close' if AutoCloseWindow is set to false). @@ -52,7 +64,7 @@ Example: \c NoReadme: \c FunctionEnd -\S{onMouseOverSection} .onMouseOverSection +\S{onmouseoversection} .onMouseOverSection This callback is called whenever the mouse position over the sections tree has changed. This allows you to set a description for each section for example. The section id on which the mouse is over currently is stored, temporarly, in $0. @@ -69,38 +81,7 @@ Example: \c SendMessage $R0 $\{WM_SETTEXT\} 0 "second section description" \c FunctionEnd -\S{onNextPage} .onNextPage - -Called when the user selects to go from one page to the next. Also called when the first page is shown (after .onInit). Call Abort from this callback in order to make the installer stay on the current page (or to make it move relative to the current page - Abort 0 means to stay put, Abort 1 means to go to the next page, Abort 2 means to go to the following page, Abort -1 means to go back a page, and so on). To figure out which page you are on, you can just keep a counter and increment it on .onNextPage, and decrement it on .onPrevPage. Note that if the directory selection page is disabled, .onNextPage and .onPrevPage are still called for it. - -Example use of .onNextPage/.onPrevPage/.onInit: - -\c Function .onInit -\c StrCpy $9 0 ; we start on page 0 -\c FunctionEnd - -\c Function .onNextPage -\c StrCmp $9 1 "" noabort -\c MessageBox MB_YESNO "advance to the second page?" IDYES noabort -\c Abort -\c noabort: -\c IntOp $9 $9 + 1 -\c FunctionEnd - -\c Function .onPrevPage -\c StrCmp $9 2 "" noabort -\c MessageBox MB_YESNO "go back to the first page?" IDYES noabort -\c Abort -\c noabort: -\c IntOp $9 $9 - 1 -\c FunctionEnd - - -\S{onPrevPage} .onPrevPage - -Called when the user selects to go from one page to the previous. Call Abort from this callback in order to make the installer stay on the current page (or pass an integer parameter to Abort to specify how many pages to move: Abort 1 means to go back one page, Abort 2 means to go back two pages, Abort -1 means to go forward a page, and so on). See .onNextPage for more information. - -\S{onSelChange} .onSelChange +\S{onselchange} .onSelChange Called when the selection changes on the component page. Useful for using with SectionSetFlags and SectionGetFlags. @@ -116,7 +97,7 @@ Example: \c NoCancelAbort: \c FunctionEnd -\S{onVerifyInstDir} .onVerifyInstDir +\S{onverifyinstdir} .onVerifyInstDir This callback enables control over whether or not an installation path is valid for your installer. This code will be called every time the user changes the install directory, so it shouldn't do anything crazy with MessageBox or the likes. If this function calls Abort, the installation path in $INSTDIR is deemed invalid. @@ -130,6 +111,12 @@ Example: \H{uninstcallbacks} Uninstall Callbacks +\S{unonguiinit} un.onGUIInit + +This callback will be called just before the first page is loaded and the installer dialog is shown, allowing you to tweak the the user interface. + +Have a look at .onGUIInit (\K{onguiinit}) for an example. + \S{unonInit} un.onInit This callback will be called when the uninstaller is nearly finished initializing. If the 'un.onInit' function calls Abort, the uninstaller will quit instantly. Note that this function can verify and/or modify $INSTDIR if necessary. @@ -151,16 +138,7 @@ or: \c found: \c FunctionEnd - -\S{unonInitDialog} un.onInitDialog - -This callback is called right after an inner dialog is created (excluding InstallOptions dialogs) and before it is shown. Useful for CreateFont, SetStaticBkColor and any other last minute text changes. - -\S{unonNextPage} un.onNextPage - -Called when the user selects 'Uninstall' or 'Close' from the uninstaller. Call Abort from this callback in order to make the uninstaller stay on the current page. - -\S{unonUninstFailed} un.onUninstFailed +\S{unonuninstfailed} un.onUninstFailed This callback is called when the user hits the 'cancel' button after the uninstall has failed (if it used the Abort command or otherwise failed). @@ -170,7 +148,7 @@ Example: \c MessageBox MB_OK "Better luck next time." \c FunctionEnd -\S{unonUninstSuccess} un.onUninstSuccess +\S{unonuninstsuccess} un.onUninstSuccess This callback is called when the uninstall was successful, right before the install window closes (which may be after the user clicks 'Close' if AutoCloseWindow is set to false). @@ -180,7 +158,7 @@ Example: \c MessageBox MB_OK "Congrats, it's gone." \c FunctionEnd -\S{unonUserAbort} un.onUserAbort +\S{unonuserabort} un.onUserAbort This callback is called when the user hits the 'cancel' button and the uninstall hasn't already failed. If this function calls Abort, the install will not be aborted. diff --git a/Docs/src/flowcontrol.but b/Docs/src/flowcontrol.but index f5dce205..c107c1e8 100644 --- a/Docs/src/flowcontrol.but +++ b/Docs/src/flowcontrol.but @@ -1,22 +1,22 @@ \C{flowcontrol} Flow Control Instructions -\H{Abort} Abort +\H{abort} Abort \c user_message -Cancels the install, stops execution of script, and displays user_message in the status display. Note: you can use this from Callback Functions (\k{callbacks}) to do special things. Note 2: When using from .onNextPage (\k{onNextPage}) or .onPrevPage (\k{onPrevPage}), the parameter to Abort can be an integer that specifies how many pages to skip. +Cancels the install, stops execution of script, and displays user_message in the status display. Note: you can use this from Callback Functions (\k{callbacks}) to do special things. Pages callbacks (\K{pages}) also uses Abort for special purposes. -\H{Call} Call +\H{call} Call \c function_name | :label_name Calls the function named function_name. If in the Uninstall section, Call can only be used with function names beginning with "un.". If the parameter starts with a ':' it will be treated as a label (so you can call to a label in your function - this is probably not going to be used most of the time). -\H{ClearErrors} ClearErrors +\H{clearerrors} ClearErrors Clears the error flag. -\H{FindWindow} FindWindow +\H{findwindow} FindWindow \c user_var(hwnd output) windowclass [windowtitle] [windowparent] [childafter] @@ -28,13 +28,13 @@ Searches for a window. Behaves like the win32 FindWindowEx(). Seaches by windowc Gets the address of the current instruction (the GetCurrentAddress) and stores it in the output user variable. This user variable then can be passed to Call or Goto. -\H{GetDlgItem} GetDlgItem +\H{getdlgitem} GetDlgItem \c user_var(output) dialog item_id Retrieves the handle of a control identified by item_id in the specified dialog box dialog. If you want to get the handle of a control on the inner dialog, first use FindWindow user_var(output) "#32770" "" $HWNDPARENT to get the handle of the inner dialog. -\H{GetFunctionAddress} GetFunctionAddress +\H{getfunctionaddress} GetFunctionAddress \c user_var(output) function_name @@ -56,37 +56,37 @@ If +offset or -offset is specified, jump is relative by offset instructions. Got If a user variable is specified, jumps to absolute address (generally you will want to get this value from a function like GetLabelAddress. I Compiler flag commands and SectionIn aren't instructions so jumping over them has no effect. -\H{IfErrors} IfErrors +\H{iferrors} IfErrors \c jumpto_iferror [jumpto_ifnoerror] Checks and clears the error flag, and if it is set, it will goto jumpto_iferror, otherwise it will goto jumpto_ifnoerror. The error flag is set by other instructions when a recoverable error (such as trying to delete a file that is in use) occurs. -\H{IfFileExists} IfFileExists +\H{iffileexists} IfFileExists \c file_to_check_for jump_if_present [jump_otherwise] Checks for existence of file(s) file_to_check_for (which can be a wildcard, or a directory), and Gotos jump_if_present if the file exists, otherwise Gotos jump_otherwise. If you want to check to see if a file is a directory, use IfFileExists DIRECTORY\\*.* -\H{IntCmp} IntCmp +\H{intcmp} IntCmp \c val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more] Compares two integers val1 and val2. If val1 and val2 are equal, Gotos jump_if_equal, otherwise if val1 < val2, Gotos jump_if_val1_less, otherwise if val1 > val2, Gotos jump_if_val1_more. -\H{IntCmpU} IntCmpU +\H{intcmpu} IntCmpU \c val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more] Compares two unsigned integers val1 and val2. If val1 and val2 are equal, Gotos jump_if_equal, otherwise if val1 < val2, Gotos jump_if_val1_less, otherwise if val1 > val2, Gotos jump_if_val1_more. Performs the comparison as unsigned integers. -\H{IsWindow} IsWindow +\H{iswindow} IsWindow \c HWND jump_if_window [jump_if_not_window] If HWND is a window, Gotos jump_if_window, otherwise, Gotos jump_if_not_window (if specified). -\H{MessageBox} MessageBox +\H{messagebox} MessageBox \c mb_option_list messagebox_text [return_check jumpto] [return_check_2 jumpto_2] @@ -144,11 +144,11 @@ Return_check can be 0 (or empty, or left off), or one of the following: If the return value of the MessageBox is return_check, the installer will Goto jumpto. -\H{Return} Return +\H{return} Return Returns from a function or section. -\H{SendMessage} SendMessage +\H{sendmessage} SendMessage \c HWND msg wparam lparam [user_var(return value)] [/TIMEOUT=time_in_ms] @@ -166,15 +166,15 @@ To send a string param, put STR: before the parameter, for example: "STR:Some st Use /TIMEOUT=time_in_ms to specify the duration, in milliseconds, of the time-out period. -\H{Quit} Quit +\H{quit} Quit Causes the installer to exit as soon as possible. After Quit is called, the installer will exit (no callback functions will get a chance to run). -\H{SetErrors} SetErrors +\H{seterrors} SetErrors Sets the error flag. -\H{StrCmp} StrCmp +\H{strcmp} StrCmp \c str1 str2 jump_if_equal [jump_if_not_equal] diff --git a/Docs/src/history.but b/Docs/src/history.but index fe0fde0f..920f2dbd 100644 --- a/Docs/src/history.but +++ b/Docs/src/history.but @@ -2,6 +2,12 @@ \e{v2.0b0} +\b New paging system + +\b Added Page and UninstPage + +\b Removed .onNextPage, .onPrevPage, .onInitDialog + \b New easier version of the Modern User Interface with better multilanguage support, InstallOptions integration etc. \b Added accelerator keys diff --git a/Docs/src/misc.but b/Docs/src/misc.but index b0eefd28..f5c7eb7f 100644 --- a/Docs/src/misc.but +++ b/Docs/src/misc.but @@ -4,59 +4,59 @@ Makes the installer window visible and brings it to the top of the window list (i.e. if a command was executed that shows itself in front of the installer, a BringToFront would bring the installer back in focus). -\H{CreateFont} CreateFont +\H{createfont} CreateFont \c user_var(handle output) face_name [height] [weight] [/ITALIC] [/UNDERLINE] [/STRIKE] Creates a font and puts its handle into user_var. For more information about the different parameters have a look at \W{http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/fontext_8fp0.asp}{MSDN's page about the Win32 API function CreateFont()}. -\H{DetailPrint} DetailPrint +\H{detailprint} DetailPrint \c user_message Adds the string "user_message" to the details view of the installer. -\H{HideWindow} HideWindow +\H{hidewindow} HideWindow Hides the installer. -\H{SetAutoClose} SetAutoClose +\H{setautoclose} SetAutoClose \c true|false Overrides the default auto window-closing flag (specified for the installer using AutoCloseWindow, and false for the uninstaller). Specify 'true' to have the install window immediately disappear after the install has completed, or 'false' to make it require a manual close. -\H{SetBrandingImage} SetBrandingImage +\H{setbrandingimage} SetBrandingImage \c [/IMGID=item_id_in_dialog] [/RESIZETOFIT] path_to_bitmap_file.bmp Sets the current bitmap file displayed as the branding image. If no IMGID is specified, the first image control found will be used, or the image control created by AddBrandingImage. Note that this bitmap must be present on the user's machine. Use File first to put it there. If /RESIZETOFIT is specified the image will be automatically resized (very poorly) to the image control size. If you used AddBrandingImage you can get this size, by compiling your script and watching for AddBrandingImage output, it will tell you the size. SetBrandingImage will not work when called from .onInit! -\H{SetDetailsView} SetDetailsView +\H{setdetailsview} SetDetailsView \c show|hide Shows or hides the details, depending on which parameter you pass. Overrides the default details view, which is set via ShowInstDetails -\H{SetDetailsPrint} SetDetailsPrint +\H{setdetailsprint} SetDetailsPrint \c none|listonly|textonly|both|lastused Sets mode at which commands print their status. None has commands be quiet, listonly has status text only added to the listbox, textonly has status text only printed to the status bar, and both enables both (the default). For extracting many small files, textonly is recommended (especially on win9x with smooth scrolling enabled). -\H{SetShellVarContext} SetShellVarContext +\H{setshellvarcontext} SetShellVarContext \c current|all Sets the context of $SMPROGRAMS and other shell folders. If set to 'current' (the default), the current user's shell folders are used. If set to 'all', the 'all users' shell folder is used. The all users folder may not be supported on all OSes. If the all users folder is not found, the current user folder will be used. -\H{SetStaticBkColor} SetStaticBkColor +\H{setstaticbkcolor} SetStaticBkColor \c hwnd color Sets a background color for a static control. Use GetDlgItem to get the handle (HWND) of the static control. -\H{Sleep} Sleep +\H{sleep} Sleep \c sleeptime_in_ms diff --git a/Docs/src/pages.but b/Docs/src/pages.but new file mode 100644 index 00000000..49fe7328 --- /dev/null +++ b/Docs/src/pages.but @@ -0,0 +1,68 @@ +\C{pages} Pages + +Each (non-silent) NSIS installer has a set of pages. Each page can be a NSIS built-in page or a custom page created by a user's function (with InstallOptions for example). + +\H{pageoreder} Ordering + +The page order is set simply by the order they are in the script. For example: + +\c Page license +\c Page components +\c Page directory +\c Page instfiles + +This code will show the license page, then the components selction page, then the directory selection page and then the install log, just like in old installers. + +Please note that you must still use LicenseText and LicenseData for the license page to show, ComponentText for the components selection page to show and DirText for the directory page to show. + +If you don't use any Page command the installer pages order will be just as in older version: license (if LicenseText and LicenseData were specified), components (if ComponentText was specified and there is more than one visible section), directory (if DirText was specified), instfiles. + +\H{pagecallbacks} Callbacks + +Each built-in page has two callback functions. The pre-function and the post-creation function. The pre-function is called right before the page is created and the post-function is called right after it is created and before it is showed so you can tweak its user interface with CreateFont (\K{createfont}), SetStaticBkColor (\K{setstaticbkcolor}) and SendMessage (\K{sendmessage}). + +A custom page has only one callback function that creates it but unlike the built-in pages this function is mandatory. + +Abort (see \K{abort}) has special usage from pages' callback functions. + +\b Use Abort from a built-in pre-function to skip the page + +\b Use Abort from a custom page creator function to go to the previous page + +Examples: + +\c Page license skipLicense +\c Page custom customPage +\c Page instfiles +\c +\c Function skipLicense +\c MessageBox MB_YES "Do you want to skip the license page?" IDNO no +\c Abort +\c no: +\c FunctionEnd +\c +\c Function customPage +\c GetTempFileName $R0 +\c File /oname=$R0 customPage.ini +\c InstallOptions::dialog $R0 +\c Delete $R0 +\c Pop $R1 +\c StrCmp $R1 "cancel" "" nocancel +\c Quit +\c nocancel: +\c StrCmp $R1 "back" "" noback +\c Abort +\c noback: +\c FunctionEnd + +\H{page} Page + +\c custom function | (license|components|directory|instfiles) [pre_function] [post_function] + +Adds an installer page. See the above sections for more information about built-in versus custom pages and about callback functions. + +\H{uninstpage} UninstPage + +\c custom function | (uninstConfirm|instfiles) [pre_function] [post_function] + +Adds an uninstaller page. See the above sections for more information about built-in versus custom pages and about callback functions. \ No newline at end of file diff --git a/Examples/gfx.nsi b/Examples/gfx.nsi index aa92f7c4..980123e9 100644 --- a/Examples/gfx.nsi +++ b/Examples/gfx.nsi @@ -6,6 +6,15 @@ ; Written by Amir Szkeley 22nd July 2002 ; +!macro BIMAGE IMAGE PARMS + Push $0 + GetTempFileName $0 + File /oname=$0 "${IMAGE}" + SetBrandingImage ${PARMS} $0 + Delete $0 + Pop $0 +!macroend + Name "Graphical effects" OutFile "gfx.exe" @@ -26,37 +35,41 @@ LicenseText "Second page" LicenseData "gfx.nsi" DirText "Lets make a third page!" +; Pages +Page license licenseImage +Page custom customPage +Page directory dirImage +Page instfiles instImage + +Function licenseImage + !insertmacro BIMAGE "${NSISDIR}\Contrib\Icons\checks1.bmp" /RESIZETOFIT + MessageBox MB_YESNO 'Would you like to skip the license page?' IDNO no + Abort + no: +FunctionEnd + +Function customPage + !insertmacro BIMAGE "${NSISDIR}\Contrib\Icons\modern.bmp" /RESIZETOFIT + MessageBox MB_YESNO 'This is a nice custom "page" with yet another image :P$\r$\n$\r$\nWould you like to go to the next page now?' IDYES yes + Abort + yes: +FunctionEnd + +Function dirImage + !insertmacro BIMAGE "${NSISDIR}\Contrib\Icons\checks2.bmp" /RESIZETOFIT +FunctionEnd + +Function instImage + !insertmacro BIMAGE "${NSISDIR}\Contrib\Icons\checks4.bmp" /RESIZETOFIT +FunctionEnd + ; Install dir InstallDir "${NSISDIR}\Examples" -; Branding helper functions -!include "branding.nsh" - -Function .onInit - !insertmacro BI_INIT $R0 -FunctionEnd - -Function .onNextPage - !insertmacro BI_NEXT -FunctionEnd - -Function .onPrevPage - !insertmacro BI_PREV -FunctionEnd - -!insertmacro BI_LIST -!insertmacro BI_LIST_ADD "${NSISDIR}\Contrib\Icons\checks1.bmp" /RESIZETOFIT -!insertmacro BI_LIST_ADD "${NSISDIR}\Contrib\Icons\checks2.bmp" /RESIZETOFIT -!insertmacro BI_LIST_ADD "${NSISDIR}\Contrib\Icons\checks4.bmp" /RESIZETOFIT -!insertmacro BI_LIST_END - Section ; You can also use the BI_NEXT macro here... MessageBox MB_YESNO "We can change the branding image from within a section too!$\nDo you want me to change it?" IDNO done - GetTempFileName $1 - File /oname=$1 "${NSISDIR}\Contrib\Icons\checksX2.bmp" - SetBrandingImage $1 - Delete $1 + !insertmacro BIMAGE "${NSISDIR}\Contrib\Icons\checksX2.bmp" "" done: WriteUninstaller uninst.exe SectionEnd @@ -64,23 +77,18 @@ SectionEnd ; Another page for uninstaller UninstallText "Another page..." -; Uninstall branding helper functions -!define BI_UNINSTALL -!include "branding.nsh" +; Uninstall pages +UninstPage uninstConfirm un.uninstImage +UninstPage instfiles un.instImage -Function un.onInit - !insertmacro BI_INIT $R0 +Function un.uninstImage + !insertmacro BIMAGE "${NSISDIR}\Contrib\Icons\checksX.bmp" /RESIZETOFIT FunctionEnd -Function un.onNextPage - !insertmacro BI_NEXT +Function un.instImage + !insertmacro BIMAGE "${NSISDIR}\Contrib\Icons\jarsonic-checks.bmp" /RESIZETOFIT FunctionEnd -!insertmacro BI_LIST -!insertmacro BI_LIST_ADD "${NSISDIR}\Contrib\Icons\checksX.bmp" /RESIZETOFIT -!insertmacro BI_LIST_ADD "${NSISDIR}\Contrib\Icons\jarsonic-checks.bmp" /RESIZETOFIT -!insertmacro BI_LIST_END - Section uninstall MessageBox MB_OK "Bla" SectionEnd \ No newline at end of file diff --git a/Plugins/InstallOptions.dll b/Plugins/InstallOptions.dll index 702aa9bf..87a049a5 100644 Binary files a/Plugins/InstallOptions.dll and b/Plugins/InstallOptions.dll differ diff --git a/Source/build.cpp b/Source/build.cpp index ace174a0..73342d8e 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -10,6 +10,7 @@ #include "ResourceEditor.h" #include "exehead/resource.h" +#include "exehead/lang.h" void CEXEBuild::define(const char *p, const char *v) { @@ -281,9 +282,16 @@ CEXEBuild::CEXEBuild() no_space_texts=false; +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT build_plugin_unload=0; +#endif last_used_lang=MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); + + build_header.common.num_pages=0; +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + build_uninst.common.num_pages=0; +#endif } int CEXEBuild::getcurdbsize() { return cur_datablock->getlen(); } @@ -1021,7 +1029,7 @@ int CEXEBuild::resolve_coderefs(const char *str) { section *sec=(section *)cur_functions->get(); int l=cur_functions->getlen()/sizeof(section); - entry *w=(entry*)cur_entries->get(); + entry *w=(entry *)cur_entries->get(); while (l-- > 0) { int x; @@ -1038,6 +1046,19 @@ int CEXEBuild::resolve_coderefs(const char *str) int x; for (x = build_uninst.code; x < build_uninst.code+build_uninst.code_size; x ++) if (resolve_instruction("\"uninstall section\"",str,w+x,x,build_uninst.code,build_uninst.code+build_uninst.code_size)) return 1; + +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (ubuild_pages.getlen()) { + page *p=(page *)ubuild_pages.get(); + int i = 0; + while (i < build_uninst.common.num_pages) { + if (resolve_call_int("uninstall pages","pre-page function",p->prefunc,&p->prefunc)) return 1; + if (resolve_call_int("uninstall pages","post-page function",p->postfunc,&p->postfunc)) return 1; + p++; + i++; + } + } +#endif } else { @@ -1057,6 +1078,18 @@ int CEXEBuild::resolve_coderefs(const char *str) sec++; cnt++; } +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (build_pages.getlen()) { + page *p=(page *)build_pages.get(); + int i = 0; + while (i < build_header.common.num_pages) { + if (resolve_call_int("pages","pre-page function",p->prefunc,&p->prefunc)) return 1; + if (resolve_call_int("pages","post-page function",p->postfunc,&p->postfunc)) return 1; + p++; + i++; + } + } +#endif } } @@ -1181,11 +1214,11 @@ int CEXEBuild::write_output(void) if (resolve_call_int("uninstall callback","un.callbacks",ns_func.find("un.onUninstSuccess",0),&build_uninst.common.code_onInstSuccess)) return PS_ERROR; if (resolve_call_int("uninstall callback","un.callbacks",ns_func.find("un.onUninstFailed",0),&build_uninst.common.code_onInstFailed)) return PS_ERROR; if (resolve_call_int("uninstall callback","un.callbacks",ns_func.find("un.onUserAbort",0),&build_uninst.common.code_onUserAbort)) return PS_ERROR; - if (resolve_call_int("uninstall callback","un.callbacks",ns_func.find("un.onNextPage",0),&build_uninst.common.code_onNextPage)) return PS_ERROR; #ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT - if (resolve_call_int("uninstall callback","un.callbacks",ns_func.find("un.onInitDialog",0),&build_uninst.common.code_onInitDialog)) return PS_ERROR; + if (resolve_call_int("uninstall callback","un.callbacks",ns_func.find("un.onGUIInit",0),&build_uninst.common.code_onGUIInit)) return PS_ERROR; #endif #endif//NSIS_SUPPORT_CODECALLBACKS + if (resolve_coderefs("uninstall")) return PS_ERROR; set_uninstall_mode(0); } @@ -1204,10 +1237,8 @@ int CEXEBuild::write_output(void) if (resolve_call_int("install callback",".callbacks",ns_func.find(".onInstFailed",0),&build_header.common.code_onInstFailed)) return PS_ERROR; if (resolve_call_int("install callback",".callbacks",ns_func.find(".onUserAbort",0),&build_header.common.code_onUserAbort)) return PS_ERROR; if (resolve_call_int("install callback",".callbacks",ns_func.find(".onVerifyInstDir",0),&build_header.code_onVerifyInstDir)) return PS_ERROR; - if (resolve_call_int("install callback",".callbacks",ns_func.find(".onNextPage",0),&build_header.common.code_onNextPage)) return PS_ERROR; - if (resolve_call_int("install callback",".callbacks",ns_func.find(".onPrevPage",0),&build_header.code_onPrevPage)) return PS_ERROR; #ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT - if (resolve_call_int("install callback",".callbacks",ns_func.find(".onInitDialog",0),&build_header.common.code_onInitDialog)) return PS_ERROR; + if (resolve_call_int("install callback",".callbacks",ns_func.find(".onGUIInit",0),&build_header.common.code_onGUIInit)) return PS_ERROR; if (resolve_call_int("install callback",".callbacks",ns_func.find(".onMouseOverSection",0),&build_header.code_onMouseOverSection)) return PS_ERROR; #endif #ifdef NSIS_CONFIG_COMPONENTPAGE @@ -1217,73 +1248,248 @@ int CEXEBuild::write_output(void) if (resolve_coderefs("install")) return PS_ERROR; - // Added by Amir Szekely 8th July 2002 - // Removes any unused resources #ifdef NSIS_CONFIG_VISIBLE_SUPPORT - try { - SCRIPT_MSG("Removing unused resources... "); - CResourceEditor re(header_data_new, exeheader_size_new); + { + page pg = { + 0, +#ifdef NSIS_SUPPORT_CODECALLBACKS + -1, + -1 +#endif + }; + int add_pages=!build_pages.getlen(); + int add_uninst_pages=!ubuild_pages.getlen(); + + int license=0; + int selcom=0; + int dir=0; + int uninst=0; + int instlog=0; + int main=2; + +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (!build_header.common.silent_install) +#endif + { #ifdef NSIS_CONFIG_LICENSEPAGE - if (IsNotSet(installer.licensedata) -#ifdef NSIS_CONFIG_SILENT_SUPPORT - || build_header.common.silent_install -#endif // NSIS_CONFIG_SILENT_SUPPORT - ) - { - re.UpdateResource(RT_DIALOG, IDD_LICENSE, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); - } -#endif // NSIS_CONFIG_LICENSEPAGE + if (!IsNotSet(installer.licensedata)) license++; +#endif #ifdef NSIS_CONFIG_COMPONENTPAGE - if (IsNotSet(installer.componenttext) -#ifdef NSIS_CONFIG_SILENT_SUPPORT - || build_header.common.silent_install -#endif // NSIS_CONFIG_SILENT_SUPPORT - ) - { - re.UpdateResource(RT_DIALOG, IDD_SELCOM, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); - re.UpdateResource(RT_BITMAP, IDB_BITMAP1, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); - } -#endif // NSIS_CONFIG_COMPONENTPAGE - if (IsNotSet(installer.text) -#ifdef NSIS_CONFIG_SILENT_SUPPORT - || build_header.common.silent_install -#endif // NSIS_CONFIG_SILENT_SUPPORT - ) - { - re.UpdateResource(RT_DIALOG, IDD_DIR, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); - } -#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT - if (!uninstaller_writes_used -#ifdef NSIS_CONFIG_SILENT_SUPPORT - || build_uninst.common.silent_install -#endif // NSIS_CONFIG_SILENT_SUPPORT - ) - { - re.UpdateResource(RT_DIALOG, IDD_UNINST, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); - } -#endif // NSIS_CONFIG_UNINSTALL_SUPPORT -#ifdef NSIS_CONFIG_SILENT_SUPPORT - if (build_header.common.silent_install -#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT - && (build_uninst.common.silent_install || !uninstaller_writes_used) -#endif // NSIS_CONFIG_UNINSTALL_SUPPORT - ) - { - re.UpdateResource(RT_DIALOG, IDD_INST, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); - re.UpdateResource(RT_DIALOG, IDD_INSTFILES, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); - if (!build_compress_whole && !build_crcchk) - re.UpdateResource(RT_DIALOG, IDD_VERIFY, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); - } -#endif // NSIS_CONFIG_SILENT_SUPPORT + if (!IsNotSet(installer.componenttext)) selcom++; +#endif + if (!IsNotSet(installer.text)) dir++; - free(header_data_new); - header_data_new = re.Save((DWORD&)exeheader_size_new); + if (!add_pages) { + int i=0; + page *p=(page *) build_pages.get(); + while (i!=build_header.common.num_pages) { + switch (p->id) { +#ifdef NSIS_CONFIG_LICENSEPAGE + case NSIS_PAGE_LICENSE: + license++; + break; +#endif +#ifdef NSIS_CONFIG_COMPONENTPAGE + case NSIS_PAGE_SELCOM: + selcom++; + break; +#endif + case NSIS_PAGE_DIR: + dir++; + break; + case NSIS_PAGE_INSTFILES: + instlog++; + break; + } + p++; + i++; + } - SCRIPT_MSG("Done!\n"); - } - catch (exception& err) { - ERROR_MSG("\nError: %s\n", err.what()); - return PS_ERROR; + if (license==1) { + ERROR_MSG("Error: %s page and %s depend on each other, both must be in the script!\n", "license", "LicenseData"); + return PS_ERROR; + } + if (selcom==1) { + ERROR_MSG("Error: %s page and %s depend on each other, both must be in the script!\n", "components", "ComponentText"); + return PS_ERROR; + } + if (dir==1) { + ERROR_MSG("Error: %s page and %s depend on each other, both must be in the script!\n", "directory selection", "DirText"); + return PS_ERROR; + } + if (!instlog) { + warning("Page instfiles not specefied, no sections will be executed!"); + } + } + else { +#ifdef NSIS_CONFIG_LICENSEPAGE + if (license) { + pg.id=NSIS_PAGE_LICENSE; + build_pages.add(&pg,sizeof(page)); + build_header.common.num_pages++; + } +#endif +#ifdef NSIS_CONFIG_COMPONENTPAGE + if (selcom) { + pg.id=NSIS_PAGE_SELCOM; + build_pages.add(&pg,sizeof(page)); + build_header.common.num_pages++; + } +#endif + if (dir) { + pg.id=NSIS_PAGE_DIR; + build_pages.add(&pg,sizeof(page)); + build_header.common.num_pages++; + } + instlog++; + pg.id=NSIS_PAGE_INSTFILES; + build_pages.add(&pg,sizeof(page)); + build_header.common.num_pages++; + pg.id=NSIS_PAGE_COMPLETED; + build_pages.add(&pg,sizeof(page)); + build_header.common.num_pages++; + } + + page *p=(page *) build_pages.get(); + for (int i=0; iback=2; // 2 - enabled, 1 - disabled, 0 - invisible + else p->back=0; + + p->next=LANG_BTN_NEXT; + +#ifdef NSIS_CONFIG_LICENSEPAGE + if (p->id==NSIS_PAGE_LICENSE) + p->next=LANG_BTN_LICENSE; +#endif + if (iid==NSIS_PAGE_INSTFILES) + p->next=LANG_BTN_INSTALL; + if (p->id==NSIS_PAGE_INSTFILES || p->id==NSIS_PAGE_COMPLETED) + p->back=1; + } + (--p)->next=LANG_BTN_CLOSE; + if (p->id==NSIS_PAGE_COMPLETED) (--p)->next=LANG_BTN_CLOSE; + } +#ifdef NSIS_CONFIG_SILENT_SUPPORT + else main--; +#endif + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (!build_uninst.common.silent_install && uninstaller_writes_used) +#endif + { + if (!IsNotSet(uninstall.uninstalltext)) uninst++; + + if (!add_uninst_pages) { + int i=0; + page *p=(page *) ubuild_pages.get(); + while (i!=build_header.common.num_pages) { + switch (p->id) { + #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + case NSIS_PAGE_UNINST: + uninst++; + break; + #endif + case NSIS_PAGE_INSTFILES: + instlog++; + break; + } + p++; + i++; + } + + if (uninst==1) { + ERROR_MSG("Error: %s page and %s depend on each other, both must be in the script!\n", "UninstallText"); + return PS_ERROR; + } + if (!instlog) { + warning("UninstPage instfiles not specefied, no sections will be executed!"); + } + } + else { + if (uninst) { + pg.id=NSIS_PAGE_UNINST; + ubuild_pages.add(&pg,sizeof(page)); + build_uninst.common.num_pages++; + } + instlog++; + pg.id=NSIS_PAGE_INSTFILES; + ubuild_pages.add(&pg,sizeof(page)); + build_uninst.common.num_pages++; + pg.id=NSIS_PAGE_COMPLETED; + ubuild_pages.add(&pg,sizeof(page)); + build_uninst.common.num_pages++; + } + + /*case NSIS_PAGE_UNINST: + p->next=LANG_BTN_UNINST; + break;*/ + + page *p=(page *) ubuild_pages.get(); + int noinstlogback=0; + for (int i=0; iback=2; // 2 - enabled, 1 - disabled, 0 - invisible + else p->back=0; + + p->next=LANG_BTN_NEXT; + + if (iid==NSIS_PAGE_INSTFILES) { + if (p->id==NSIS_PAGE_UNINST) + noinstlogback=1; + p->next=LANG_BTN_UNINST; + } + if (p->id==NSIS_PAGE_INSTFILES || p->id==NSIS_PAGE_COMPLETED) + p->back=noinstlogback?0:1; + } + (--p)->next=LANG_BTN_CLOSE; + if (p->id==NSIS_PAGE_COMPLETED) (--p)->next=LANG_BTN_CLOSE; + } +#ifdef NSIS_CONFIG_SILENT_SUPPORT + else +#endif +#endif + main--; + + try { + SCRIPT_MSG("Removing unused resources... "); + CResourceEditor re(header_data_new, exeheader_size_new); + #ifdef NSIS_CONFIG_LICENSEPAGE + if (!license) { + re.UpdateResource(RT_DIALOG, IDD_LICENSE, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + } + #endif // NSIS_CONFIG_LICENSEPAGE + #ifdef NSIS_CONFIG_COMPONENTPAGE + if (!selcom) { + re.UpdateResource(RT_DIALOG, IDD_SELCOM, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + re.UpdateResource(RT_BITMAP, IDB_BITMAP1, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + } + #endif // NSIS_CONFIG_COMPONENTPAGE + if (!dir) { + re.UpdateResource(RT_DIALOG, IDD_DIR, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + } + #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (!uninst) { + re.UpdateResource(RT_DIALOG, IDD_UNINST, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + } + #endif // NSIS_CONFIG_UNINSTALL_SUPPORT + if (!instlog) { + re.UpdateResource(RT_DIALOG, IDD_INSTFILES, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + } + if (!main) { + re.UpdateResource(RT_DIALOG, IDD_INST, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + if (!build_compress_whole && !build_crcchk) + re.UpdateResource(RT_DIALOG, IDD_VERIFY, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + } + + free(header_data_new); + header_data_new = re.Save((DWORD&)exeheader_size_new); + + SCRIPT_MSG("Done!\n"); + } + catch (exception& err) { + ERROR_MSG("\nError: %s\n", err.what()); + return PS_ERROR; + } } #endif // NSIS_CONFIG_VISIBLE_SUPPORT @@ -1415,6 +1621,9 @@ int CEXEBuild::write_output(void) GrowBuf hdrcomp; hdrcomp.add(&build_header,sizeof(build_header)); hdrcomp.add(build_sections.get(),build_sections.getlen()); +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + hdrcomp.add(build_pages.get(),build_pages.getlen()); +#endif hdrcomp.add(build_entries.get(),build_entries.getlen()); hdrcomp.add(build_strlist.get(),build_strlist.getlen()); hdrcomp.add(build_langtables.get(),build_langtables.getlen()); @@ -1692,6 +1901,9 @@ int CEXEBuild::uninstall_generate() GrowBuf udata; udata.add(&build_uninst,sizeof(build_uninst)); +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + udata.add(ubuild_pages.get(),ubuild_pages.getlen()); +#endif udata.add(ubuild_entries.get(),ubuild_entries.getlen()); udata.add(ubuild_strlist.get(),ubuild_strlist.getlen()); udata.add(ubuild_langtables.get(),ubuild_langtables.getlen()); diff --git a/Source/build.h b/Source/build.h index af818f16..ae71af35 100644 --- a/Source/build.h +++ b/Source/build.h @@ -2,6 +2,7 @@ #define _BUILD_H_ #include +#include using namespace std; #include "strlist.h" @@ -201,6 +202,7 @@ class CEXEBuild { StringList build_strlist,ubuild_strlist; GrowBuf build_langtables, ubuild_langtables; StringList build_userlangstrings, ubuild_userlangstrings; + GrowBuf build_pages, ubuild_pages; MMapBuf build_datablock, ubuild_datablock; // use GrowBuf here instead of MMapBuf if you want IGrowBuf *cur_datablock; diff --git a/Source/exehead/Ui.c b/Source/exehead/Ui.c index dafd43b6..50b778f5 100644 --- a/Source/exehead/Ui.c +++ b/Source/exehead/Ui.c @@ -39,7 +39,7 @@ #define LB_ICONHEIGHT 20 HICON g_hIcon; -static char gDontFookWithFocus = 0; +static int gDontFookWithFocus = 0; // Added by Amir Szekely 3rd August 2002 char *language_tables; @@ -51,9 +51,9 @@ int g_quit_flag; // set when Quit has been called (meaning bail out ASAP) #error invalid value for NSIS_MAX_INST_TYPES #endif -char g_autoclose; -char g_noicon; +int g_autoclose; int progress_bar_pos, progress_bar_len; +int g_is_uninstaller; HWND g_progresswnd; @@ -98,16 +98,9 @@ HWND NSISCALL bgWnd_Init(); HWND insthwnd, insthwnd2,insthwndbutton; void *g_inst_combinedheader; +page *g_inst_page; section *g_inst_section; entry *g_inst_entry; -#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT -int g_is_uninstaller; -static int g_max_page=1; -static int g_page_offs=4; -#else -#define g_max_page 3 -#define g_page_offs 0 -#endif static int m_page=-1,m_abort; static HWND m_curwnd, m_bgwnd, m_hwndOK, m_hwndCancel; @@ -272,8 +265,9 @@ lang_again: } myitoa(state_language, *(LANGID*)language_table); - +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT SendMessage(m_bgwnd, WM_SETTEXT, 0, (LPARAM)process_string_fromtab(g_caption,LANG_CAPTION)); +#endif } int NSISCALL ui_doinstall(void) @@ -282,12 +276,8 @@ int NSISCALL ui_doinstall(void) g_autoclose=g_inst_cmnheader->misc_flags&1; #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT if (!g_is_uninstaller) - { - g_max_page=3; - g_page_offs=0; -#else - { #endif + { if (!is_valid_instpath(state_install_directory)) { if (g_inst_header->install_reg_key_ptr) @@ -443,9 +433,7 @@ BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_INITDIALOG || uMsg == WM_NOTIFY_OUTER_NEXT) { - int iscp=0,islp=0,isdp=0,ispotentiallydp=0; - int delta=(uMsg == WM_NOTIFY_OUTER_NEXT)?wParam:0; - int prev_page=m_page; + #define delta wParam static struct { char *id; @@ -455,19 +443,15 @@ BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { #ifdef NSIS_CONFIG_LICENSEPAGE {MAKEINTRESOURCE(IDD_LICENSE),LicenseProc}, -#else - {NULL,NULL}, #endif #ifdef NSIS_CONFIG_COMPONENTPAGE {MAKEINTRESOURCE(IDD_SELCOM),SelProc}, -#else - {NULL,NULL}, #endif {MAKEINTRESOURCE(IDD_DIR),DirProc}, {MAKEINTRESOURCE(IDD_INSTFILES),InstProc}, + {NULL,NULL}, // imaginary completed page #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT - {MAKEINTRESOURCE(IDD_UNINST),UninstProc}, - {MAKEINTRESOURCE(IDD_INSTFILES),InstProc}, + {MAKEINTRESOURCE(IDD_UNINST),UninstProc} #endif }; @@ -479,126 +463,96 @@ BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) SetDlgItemTextFromLang(hwndDlg,IDC_VERSTR,LANG_BRANDING); SetClassLong(hwndDlg,GCL_HICON,(long)g_hIcon); SetDlgItemTextFromLang(hwndDlg,IDCANCEL,LANG_BTN_CANCEL); -#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT - if (!g_is_uninstaller) + SetDlgItemTextFromLang(hwndDlg,IDC_BACK,LANG_BTN_BACK); +#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_ENHANCEDUI_SUPPORT) + ExecuteCodeSegment(g_inst_cmnheader->code_onGUIInit,NULL); #endif - SetDlgItemTextFromLang(hwndDlg,IDC_BACK,LANG_BTN_BACK); ShowWindow(hwndDlg,SW_SHOW); } -#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT - if (g_is_uninstaller) - { - islp = LANG_STR_TAB(LANG_UNINST_TEXT); - iscp++; - } - else -#endif//NSIS_CONFIG_UNINSTALL_SUPPORT - { -#ifdef NSIS_CONFIG_LICENSEPAGE - islp = LANG_STR_TAB(LANG_LICENSE_DATA); -#endif//NSIS_CONFIG_LICENSEPAGE -#ifdef NSIS_CONFIG_COMPONENTPAGE - iscp = LANG_STR_TAB(LANG_COMP_TEXT); -#endif//NSIS_CONFIG_COMPONENTPAGE - ispotentiallydp = LANG_STR_TAB(LANG_DIR_TEXT); - if (ispotentiallydp && - !((g_inst_cmnheader->misc_flags&2) && - is_valid_instpath(state_install_directory) -#ifdef NSIS_SUPPORT_CODECALLBACKS - && !ExecuteCodeSegment(g_inst_header->code_onVerifyInstDir,NULL) -#endif//NSIS_SUPPORT_CODECALLBACKS - )) isdp++; - } +nextPage: - if (m_page<=0) delta=1; - do - { - int count=1; // Number of pages to move by -#ifdef NSIS_SUPPORT_CODECALLBACKS - // Call onNext|PrevPage for every not-definitely-disabled page - if (ExecuteCodeSegment(delta>0?g_inst_cmnheader->code_onNextPage:g_inst_header->code_onPrevPage,NULL)) - { - if (g_quit_flag) // Quit instruction used? - m_page=count=-1; - // Mmm - relies on ps_tmpbuf still being set from the Abort command - safe? - else if ((count = myatoi(ps_tmpbuf)) != 0) - count /= (delta = (count>0?1:-1)); - } -#endif//NSIS_SUPPORT_CODECALLBACKS - // Skip any definitely-disabled pages, then the required number of pages - while ((m_page==0 && !islp) || (m_page==1 && !iscp) || (m_page==2 && !ispotentiallydp) || (--count>=0)) - m_page+=delta; - // Skip any possibly-disabled pages - } while ((m_page >= 0) && (m_page <= g_max_page) && (m_page==2 && !isdp)); + if (m_page<0) delta=1; + m_page+=delta; #ifdef NSIS_SUPPORT_CODECALLBACKS - if (m_page>g_max_page) ExecuteCodeSegment(g_inst_cmnheader->code_onInstSuccess,NULL); + if (m_page==g_inst_cmnheader->num_pages) ExecuteCodeSegment(g_inst_cmnheader->code_onInstSuccess,NULL); #endif//NSIS_SUPPORT_CODECALLBACKS - if (m_curwnd && (m_page!=prev_page)) + if (g_quit_flag || m_page < 0 || m_page == g_inst_cmnheader->num_pages) { DestroyWindow(m_curwnd); - m_curwnd=0; - } - - if (m_page < 0 || m_page > g_max_page) EndDialog(hwndDlg,0); - else if (!m_curwnd) + } + else { HWND hwndtmp; - int str = - (m_page == g_max_page) ? LANG_BTN_CLOSE : -#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT - g_is_uninstaller ? LANG_BTN_UNINST : -#endif -#ifdef NSIS_CONFIG_LICENSEPAGE - (m_page == 0) ? LANG_BTN_LICENSE : -#endif - (m_page == 2 || (m_page == 1 && !isdp)) ? LANG_BTN_INSTALL : - LANG_BTN_NEXT; - SetDlgItemTextFromLang(hwndDlg,IDOK,str); - mystrcpy(g_tmp,g_caption); - process_string_fromtab(g_tmp+mystrlen(g_tmp),LANG_SUBCAPTION(m_page)); + int page_id=g_inst_page[m_page].id; - SetWindowText(hwndDlg,g_tmp); + SetDlgItemTextFromLang(hwndDlg,IDOK,g_inst_page[m_page].next); + + hwndtmp=GetDlgItem(hwndDlg,IDC_BACK); + ShowWindow(hwndtmp,g_inst_page[m_page].back?SW_SHOWNA:SW_HIDE); + EnableWindow(hwndtmp, g_inst_page[m_page].back&2); - gDontFookWithFocus = 0; - m_curwnd=CreateDialog(g_hInstance,windows[g_page_offs+m_page].id,hwndDlg,windows[g_page_offs+m_page].proc); - if (m_curwnd) + if (page_id!=NSIS_PAGE_COMPLETED) DestroyWindow(m_curwnd); + else if (g_autoclose) goto nextPage; + + if (page_id>=0) // NSIS page { - RECT r; - GetWindowRect(GetDlgItem(hwndDlg,IDC_CHILDRECT),&r); - ScreenToClient(hwndDlg,(LPPOINT)&r); - SetWindowPos(m_curwnd,0,r.left,r.top,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER); #ifdef NSIS_SUPPORT_CODECALLBACKS - ExecuteCodeSegment(g_inst_cmnheader->code_onInitDialog,NULL); + if (ExecuteCodeSegment(g_inst_page[m_page].prefunc,NULL)) + goto nextPage; + else #endif //NSIS_SUPPORT_CODECALLBACKS - SendMessage(m_curwnd, WM_NOTIFY_START, 0, 0); - ShowWindow(m_curwnd,SW_SHOWNA); + { + mystrcpy(g_tmp,g_caption); + process_string_fromtab( + g_tmp+mystrlen(g_tmp), + LANG_SUBCAPTION(page_id-(g_is_uninstaller?NSIS_PAGE_INSTFILES:0)) + ); + + SetWindowText(hwndDlg,g_tmp); + + gDontFookWithFocus = 0; + m_curwnd=CreateDialog(g_hInstance,windows[page_id].id,hwndDlg,windows[page_id].proc); + if (m_curwnd) + { + RECT r; + GetWindowRect(GetDlgItem(hwndDlg,IDC_CHILDRECT),&r); + ScreenToClient(hwndDlg,(LPPOINT)&r); + SetWindowPos(m_curwnd,0,r.left,r.top,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER); + SendMessage(m_curwnd, WM_NOTIFY_START, 0, 0); + ShowWindow(m_curwnd,SW_SHOWNA); + } + + //XGE 5th September 2002 - Do *not* move the focus to the OK button if we are + //on the license page, instead we want the focus left alone because in + //WM_INITDIALOG it is given to the richedit control. + if (!gDontFookWithFocus) + SetFocus(m_hwndOK); + //XGE End + } + } +#ifdef NSIS_SUPPORT_CODECALLBACKS + else // User custom page + { + if (ExecuteCodeSegment(g_inst_page[m_page].prefunc,NULL)) + delta=-1; + else + delta=1; + goto nextPage; } - hwndtmp=GetDlgItem(hwndDlg,IDC_BACK); -#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT - ShowWindow(hwndtmp,(m_page&&!g_is_uninstaller)?SW_SHOWNA:SW_HIDE); - if (!g_is_uninstaller) -#else - ShowWindow(hwndtmp,m_page?SW_SHOWNA:SW_HIDE); -#endif - EnableWindow(hwndtmp, (m_page==1&&islp) || (m_page==2&&(islp||iscp))); -//XGE 5th September 2002 - Do *not* move the focus to the OK button if we are -//on the license page, instead we want the focus left alone because in -//WM_INITDIALOG it is given to the richedit control. - if (!gDontFookWithFocus) - SetFocus(m_hwndOK); -//XGE End + ExecuteCodeSegment(g_inst_page[m_page].postfunc,NULL); +#endif //NSIS_SUPPORT_CODECALLBACKS } } if (uMsg == WM_COMMAND) { int id=LOWORD(wParam); - if (id == IDOK && m_curwnd) + if (id == IDOK) { outernotify(1); } @@ -606,9 +560,8 @@ BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT !g_is_uninstaller && #endif - (id == IDC_BACK && m_curwnd && m_page>0)) + (id == IDC_BACK && m_page>0)) { - EnableWindow(m_hwndOK, TRUE); outernotify(-1); } if (id == IDCANCEL) @@ -900,7 +853,7 @@ static DWORD WINAPI newTreeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l SendMessage(m_curwnd,WM_TREEVIEW_KEYHACK,0,0); return 0; } -#ifdef NSIS_SUPPORT_CODECALLBACKS +#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_ENHANCEDUI_SUPPORT) if (uMsg == WM_DESTROY) { last_item=-1; } @@ -927,12 +880,13 @@ static DWORD WINAPI newTreeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l mystrcpy(g_tmp, g_usrvars[0]); myitoa(g_usrvars[0], last_item); + ExecuteCodeSegment(g_inst_header->code_onMouseOverSection,NULL); mystrcpy(g_usrvars[0], g_tmp); } } -#endif//NSIS_SUPPORT_CODECALLBACKS +#endif//NSIS_SUPPORT_CODECALLBACKS && NSIS_CONFIG_ENHANCEDUI_SUPPORT return CallWindowProc((WNDPROC)oldTreeWndProc,hwnd,uMsg,wParam,lParam); } @@ -1166,11 +1120,11 @@ static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar } // not ro } // was valid click } // was click or hack -#ifdef NSIS_SUPPORT_CODECALLBACKS +#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_ENHANCEDUI_SUPPORT) else if (lpnmh->code == TVN_SELCHANGED) { SendMessage(hwndTree1, WM_USER+0x19, 0, ((LPNMTREEVIEW)lpnmh)->itemNew.lParam); } -#endif//NSIS_SUPPORT_CODECALLBACKS +#endif//NSIS_SUPPORT_CODECALLBACKS && NSIS_CONFIG_ENHANCEDUI_SUPPORT } } if (uMsg == WM_COMMAND) @@ -1403,19 +1357,10 @@ static BOOL CALLBACK InstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa { HWND h=m_hwndOK; EnableWindow(h,1); - if (!g_autoclose) - { - ShowWindow(g_hwnd,SW_SHOWNA); - mystrcpy(g_tmp,g_caption); - process_string_fromtab(g_tmp+mystrlen(g_tmp),LANG_SUBCAPTION(g_max_page+1)); - update_status_text_from_lang(LANG_COMPLETED,""); - SetWindowText(g_hwnd,g_tmp); - SetFocus(h); - } - else - { - outernotify(1); - } + ShowWindow(g_hwnd,SW_SHOWNA); + update_status_text_from_lang(LANG_COMPLETED,""); + outernotify(1); + SetFocus(h); } else { diff --git a/Source/exehead/exec.c b/Source/exehead/exec.c index 8b3ede26..c0405286 100644 --- a/Source/exehead/exec.c +++ b/Source/exehead/exec.c @@ -795,6 +795,7 @@ static int NSISCALL ExecuteEntry(entry *entry_) f.lfItalic=parm4&1; f.lfUnderline=parm4&2; f.lfStrikeOut=parm4&4; + f.lfCharSet=DEFAULT_CHARSET; process_string_fromtab(f.lfFaceName,parm1); myitoa(var0,(int)CreateFontIndirect(&f)); } @@ -959,7 +960,7 @@ static int NSISCALL ExecuteEntry(entry *entry_) update_status_text_from_lang(LANG_CANNOTFINDSYMBOL,buf1); log_printf3("Error registering DLL: %s not found in %s",buf1,buf0); } - if (!parm3) FreeLibrary(h); + if (!parm3) while (FreeLibrary(h)); // saves 2 bytes - FreeLibrary((HANDLE)((unsigned long)h&(unsigned long)parm3)); } else diff --git a/Source/exehead/fileform.c b/Source/exehead/fileform.c index 0c9f7714..02b6830a 100644 --- a/Source/exehead/fileform.c +++ b/Source/exehead/fileform.c @@ -99,15 +99,16 @@ const char * NSISCALL loadHeaders(void) if (h.flags&FH_FLAGS_UNINSTALL) { g_is_uninstaller++; - g_inst_entry=(entry *) ((g_inst_uninstheader) + 1); + g_inst_page=(page *) (g_inst_uninstheader + 1); } else #endif { g_inst_section=(section *) (g_inst_header + 1); - g_inst_entry=(entry *) (g_inst_section + g_inst_header->num_sections); + g_inst_page=(page *) (g_inst_section + g_inst_header->num_sections); } - g_db_strtab = (char *)(g_inst_entry + g_inst_cmnheader->num_entries); + g_inst_entry=(entry *) (g_inst_page + g_inst_cmnheader->num_pages); + g_db_strtab = (char *) (g_inst_entry + g_inst_cmnheader->num_entries); return 0; } diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index 2dabc643..986ed799 100644 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -13,6 +13,7 @@ // sections (20 bytes each) // (if uninstall) // uninstall_header (~116 bytes) +// pages (12 bytes each) // entries (24 bytes each) // string table // language tables @@ -182,9 +183,25 @@ enum }; +#define FH_FLAGS_MASK 15 +#define FH_FLAGS_CRC 1 +#define FH_FLAGS_UNINSTALL 2 +#ifdef NSIS_CONFIG_SILENT_SUPPORT +#define FH_FLAGS_SILENT 4 +#endif +// Added by Amir Szekely 23rd July 2002 +#define FH_FLAGS_FORCE_CRC 8 + +#define FH_SIG 0xDEADBEEF + +// neato surprise signature that goes in firstheader. :) +#define FH_INT1 0x6C6C754E +#define FH_INT2 0x74666F73 +#define FH_INT3 0x74736E49 + typedef struct { - int flags; // &1=CRC, &2=uninstall, &4=silent + int flags; // &1=CRC, &2=uninstall, &4=silent, &8=force CRC int siginfo; // FH_SIG int nsinst[3]; // FH_INT1,FH_INT2,FH_INT3 @@ -199,17 +216,22 @@ typedef struct // Strings common to both installers and uninstallers typedef struct { - // unprocessed strings - int branding; - int cancelbutton; - int showdetailsbutton; - int completed; - int closebutton; // "Close" int name; // name of installer + // unprocessed strings +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + int branding; + int backbutton; + int nextbutton; + int cancelbutton; + int showdetailsbutton; + int closebutton; // "Close" + int completed; + // processed strings - int caption; // name of installer + " Setup" or whatever. int subcaptions[5]; +#endif + int caption; // name of installer + " Setup" or whatever. #ifdef NSIS_SUPPORT_FILE int fileerrtext; @@ -278,6 +300,8 @@ typedef struct int num_entries; // total number of entries int num_string_bytes; // total number of bytes taken by strings + int num_pages; // number of used pages (including custom pages) + #ifdef NSIS_SUPPORT_BGBG int bg_color1, bg_color2, bg_textcolor; #endif @@ -289,9 +313,8 @@ typedef struct int code_onInstSuccess; int code_onInstFailed; int code_onUserAbort; - int code_onNextPage; #ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT - int code_onInitDialog; + int code_onGUIInit; #endif #endif//NSIS_SUPPORT_CODECALLBACKS @@ -309,8 +332,6 @@ typedef struct { // these first strings are literals (should not be encoded) #ifdef NSIS_CONFIG_VISIBLE_SUPPORT - int backbutton; - int nextbutton; int browse; // "Browse..." int installbutton; // "Install" int spacerequired; // "Space required: " @@ -364,7 +385,6 @@ typedef struct #ifdef NSIS_SUPPORT_CODECALLBACKS // .on* calls - int code_onPrevPage; int code_onVerifyInstDir; #ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT int code_onMouseOverSection; @@ -418,22 +438,33 @@ typedef struct int offsets[MAX_ENTRY_OFFSETS]; // count and meaning of offsets depend on 'which' } entry; - -#define FH_FLAGS_MASK 15 -#define FH_FLAGS_CRC 1 -#define FH_FLAGS_UNINSTALL 2 -#ifdef NSIS_CONFIG_SILENT_SUPPORT -#define FH_FLAGS_SILENT 4 +enum +{ + NSIS_PAGE_CUSTOM = -1, +#ifdef NSIS_CONFIG_LICENSEPAGE + NSIS_PAGE_LICENSE, #endif -// Added by Amir Szekely 23rd July 2002 -#define FH_FLAGS_FORCE_CRC 8 +#ifdef NSIS_CONFIG_COMPONENTPAGE + NSIS_PAGE_SELCOM, +#endif + NSIS_PAGE_DIR, + NSIS_PAGE_INSTFILES, + NSIS_PAGE_COMPLETED, +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + NSIS_PAGE_UNINST +#endif +}; -#define FH_SIG 0xDEADBEEF - -// neato surprise signature that goes in firstheader. :) -#define FH_INT1 0x6C6C754E -#define FH_INT2 0x74666F73 -#define FH_INT3 0x74736E49 +typedef struct +{ + int id; // index in the pages array +#ifdef NSIS_SUPPORT_CODECALLBACKS + int prefunc; // function to use Abort in, or show the custom page if id == NSIS_PAGE_CUSTOM + int postfunc; // function to do stuff after the page is shown +#endif //NSIS_SUPPORT_CODECALLBACKS + int next; + int back; +} page; // the following are only used/implemented in exehead, not makensis. diff --git a/Source/exehead/lang.h b/Source/exehead/lang.h index 636ebdae..f6796c81 100644 --- a/Source/exehead/lang.h +++ b/Source/exehead/lang.h @@ -46,8 +46,6 @@ #define INSTALL_STR(x) (~((sizeof(common_strings) + FIELD_OFFSET(installer_strings, x)) / sizeof(int))) // Installer specific strings -#define LANG_BTN_BACK (INSTALL_STR(backbutton)) -#define LANG_BTN_NEXT (INSTALL_STR(nextbutton)) #define LANG_BTN_BROWSE (INSTALL_STR(browse)) #define LANG_BTN_INSTALL (INSTALL_STR(installbutton)) #define LANG_SPACE_REQ (INSTALL_STR(spacerequired)) @@ -71,6 +69,8 @@ #define COMMON_STR(x) (~(FIELD_OFFSET(common_strings, x) / sizeof(int))) // Common strings +#define LANG_BTN_NEXT (COMMON_STR(nextbutton)) +#define LANG_BTN_BACK (COMMON_STR(backbutton)) #define LANG_BRANDING (COMMON_STR(branding)) #define LANG_BTN_CANCEL (COMMON_STR(cancelbutton)) #define LANG_BTN_DETAILS (COMMON_STR(showdetailsbutton)) diff --git a/Source/exehead/ui.h b/Source/exehead/ui.h index 480fdfc4..96ae16f4 100644 --- a/Source/exehead/ui.h +++ b/Source/exehead/ui.h @@ -10,8 +10,9 @@ void NSISCALL update_status_text_from_lang(int id, const char *text2); void NSISCALL update_status_text(const char *text1, const char *text2); extern int ui_st_updateflag; -extern char g_autoclose; +extern int g_autoclose; extern void *g_inst_combinedheader; +extern page *g_inst_page; extern section *g_inst_section; extern entry *g_inst_entry; diff --git a/Source/lang.cpp b/Source/lang.cpp index e1189268..7728be84 100644 --- a/Source/lang.cpp +++ b/Source/lang.cpp @@ -123,25 +123,27 @@ int CEXEBuild::SetString(char *string, int id, int process, StringTable *table) #define HANDLE_STRING_U(id,strname) case id: ustr=&(table->strname); break; #endif switch (id) { +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + HANDLE_STRING_C(NLF_COMPLETED, common.completed); + HANDLE_STRING_C(NLF_BTN_NEXT, common.nextbutton); + HANDLE_STRING_C(NLF_BTN_BACK, common.backbutton); HANDLE_STRING_C(NLF_BRANDING, common.branding); HANDLE_STRING_C(NLF_BTN_CANCEL, common.cancelbutton); HANDLE_STRING_C(NLF_BTN_CLOSE, common.closebutton); HANDLE_STRING_C(NLF_BTN_DETAILS, common.showdetailsbutton); - HANDLE_STRING_C(NLF_COMPLETED, common.completed); +#endif +#ifdef NSIS_CONFIG_LICENSEPAGE #ifdef NSIS_SUPPORT_FILE HANDLE_STRING_C(NLF_FILE_ERROR, common.fileerrtext); #endif +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT HANDLE_STRING_I(NLF_CAPTION, common.caption); HANDLE_STRING_I(NLF_SUBCAPTION_LICENSE, common.subcaptions[0]); HANDLE_STRING_I(NLF_SUBCAPTION_OPTIONS, common.subcaptions[1]); HANDLE_STRING_I(NLF_SUBCAPTION_DIR, common.subcaptions[2]); HANDLE_STRING_I(NLF_SUBCAPTION_INSTFILES, common.subcaptions[3]); HANDLE_STRING_I(NLF_SUBCAPTION_COMPLETED, common.subcaptions[4]); -#ifdef NSIS_CONFIG_VISIBLE_SUPPORT - HANDLE_STRING_I(NLF_BTN_NEXT, installer.nextbutton); - HANDLE_STRING_I(NLF_BTN_BACK, installer.backbutton); -#ifdef NSIS_CONFIG_LICENSEPAGE HANDLE_STRING_I(NLF_BTN_LICENSE, installer.licensebutton); #endif HANDLE_STRING_I(NLF_BTN_INSTALL, installer.installbutton); @@ -154,15 +156,16 @@ int CEXEBuild::SetString(char *string, int id, int process, StringTable *table) HANDLE_STRING_I(NLF_DIR_SUBTEXT, installer.dirsubtext); HANDLE_STRING_I(NLF_SPACE_AVAIL, installer.spaceavailable); HANDLE_STRING_I(NLF_SPACE_REQ, installer.spacerequired); -#endif #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT HANDLE_STRING_U(NLF_UCAPTION, ucommon.caption); - HANDLE_STRING_U(NLF_USUBCAPTION_CONFIRM, ucommon.subcaptions[0]); - HANDLE_STRING_U(NLF_USUBCAPTION_INSTFILES, ucommon.subcaptions[1]); - HANDLE_STRING_U(NLF_USUBCAPTION_COMPLETED, ucommon.subcaptions[2]); + HANDLE_STRING_U(NLF_USUBCAPTION_INSTFILES, ucommon.subcaptions[0]); + HANDLE_STRING_U(NLF_USUBCAPTION_COMPLETED, ucommon.subcaptions[1]); + HANDLE_STRING_U(NLF_USUBCAPTION_CONFIRM, ucommon.subcaptions[2]); HANDLE_STRING_U(NLF_BTN_UNINSTALL, uninstall.uninstbutton); HANDLE_STRING_U(NLF_UNINST_SUBTEXT, uninstall.uninstalltext2); +#endif + #endif HANDLE_STRING_C(LANG_NAME, common.name); @@ -397,7 +400,7 @@ void CEXEBuild::FillDefaultsIfNeeded(StringTable *table, NLF *nlf/*=0*/) { // Changed by Amir Szekely 22nd July 2002 // Adds the ability to disable space texts if (!table->installer.spacerequired && !no_space_texts) table->installer.spacerequired=add_string_main(str(NLF_SPACE_REQ),0); - if (!table->installer.nextbutton) table->installer.nextbutton=add_string_main(str(NLF_BTN_NEXT),0); + if (!table->common.nextbutton) table->common.nextbutton=add_string_main(str(NLF_BTN_NEXT),0); if (!table->installer.installbutton) table->installer.installbutton=add_string_main(str(NLF_BTN_INSTALL),0); } @@ -412,7 +415,7 @@ void CEXEBuild::FillDefaultsIfNeeded(StringTable *table, NLF *nlf/*=0*/) { wsprintf(buf,str(NLF_BRANDING),NSIS_VERSION); table->common.branding=add_string_main(buf,0); } - if (!table->installer.backbutton) table->installer.backbutton=add_string_main(str(NLF_BTN_BACK),0); + if (!table->common.backbutton) table->common.backbutton=add_string_main(str(NLF_BTN_BACK),0); if (!table->common.cancelbutton) table->common.cancelbutton=add_string_main(str(NLF_BTN_CANCEL),0); if (!table->common.showdetailsbutton) table->common.showdetailsbutton=add_string_main(str(NLF_BTN_DETAILS),0); @@ -433,23 +436,27 @@ void CEXEBuild::FillDefaultsIfNeeded(StringTable *table, NLF *nlf/*=0*/) { if (uninstaller_writes_used) { if (!table->uninstall.uninstalltext2) table->uninstall.uninstalltext2=add_string_uninst(str(NLF_UNINST_SUBTEXT),0); - if (!table->ucommon.subcaptions[0]) - table->ucommon.subcaptions[0]=add_string_uninst(str(NLF_USUBCAPTION_CONFIRM)); - if (!table->ucommon.subcaptions[1]) - table->ucommon.subcaptions[1]=add_string_uninst(str(NLF_USUBCAPTION_INSTFILES)); - if (!table->ucommon.subcaptions[2]) - table->ucommon.subcaptions[2]=add_string_uninst(str(NLF_USUBCAPTION_COMPLETED)); if (!table->ucommon.caption) { char buf[1024]; wsprintf(buf,str(NLF_UCAPTION),ubuild_strlist.get()+table->ucommon.name); table->ucommon.caption=add_string_uninst(buf); } +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + if (!table->ucommon.subcaptions[0]) + table->ucommon.subcaptions[0]=add_string_uninst(str(NLF_USUBCAPTION_INSTFILES)); + if (!table->ucommon.subcaptions[1]) + table->ucommon.subcaptions[1]=add_string_uninst(str(NLF_USUBCAPTION_COMPLETED)); + if (!table->ucommon.subcaptions[2]) + table->ucommon.subcaptions[2]=add_string_uninst(str(NLF_USUBCAPTION_CONFIRM)); table->ucommon.branding=add_string_uninst(build_strlist.get() + table->common.branding,0); + table->ucommon.backbutton=add_string_uninst(build_strlist.get() + table->common.backbutton,0); + table->ucommon.nextbutton=add_string_uninst(build_strlist.get() + table->common.nextbutton,0); table->ucommon.cancelbutton=add_string_uninst(build_strlist.get() + table->common.cancelbutton,0); table->ucommon.showdetailsbutton=add_string_uninst(build_strlist.get() + table->common.showdetailsbutton,0); table->ucommon.closebutton=add_string_uninst(build_strlist.get() + table->common.closebutton,0); table->ucommon.completed=add_string_uninst(build_strlist.get() + table->common.completed,0); +#endif if (!table->uninstall.uninstbutton) table->uninstall.uninstbutton=add_string_uninst(str(NLF_BTN_UNINSTALL),0); } diff --git a/Source/lang.h b/Source/lang.h index ad676e9f..e63edd43 100644 --- a/Source/lang.h +++ b/Source/lang.h @@ -20,70 +20,72 @@ struct StringTable { #define NLF_VERSION 2 #define NLF_STRINGS 57 -#define NLF_BRANDING 0 -#define NLF_CAPTION 1 -#define NLF_UCAPTION 2 -#define NLF_SUBCAPTION_LICENSE 3 -#define NLF_SUBCAPTION_OPTIONS 4 -#define NLF_SUBCAPTION_DIR 5 -#define NLF_SUBCAPTION_INSTFILES 6 -#define NLF_SUBCAPTION_COMPLETED 7 -#define NLF_USUBCAPTION_CONFIRM 8 -#define NLF_USUBCAPTION_INSTFILES 9 -#define NLF_USUBCAPTION_COMPLETED 10 -#define NLF_BTN_BACK 11 -#define NLF_BTN_NEXT 12 -#define NLF_BTN_LICENSE 13 -#define NLF_BTN_INSTALL 14 -#define NLF_BTN_UNINSTALL 15 -#define NLF_BTN_CANCEL 16 -#define NLF_BTN_CLOSE 17 -#define NLF_BTN_BROWSE 18 -#define NLF_BTN_DETAILS 19 -#define NLF_DEF_NAME 20 -#define NLF_COMPLETED 21 -#define NLF_COMP_CUSTOM 22 -#define NLF_COMP_SUBTEXT1 23 -#define NLF_COMP_SUBTEXT1_NO_INST_TYPES 24 -#define NLF_COMP_SUBTEXT2 25 -#define NLF_DIR_SUBTEXT 26 -#define NLF_SPACE_AVAIL 27 -#define NLF_SPACE_REQ 28 -#define NLF_UNINST_SUBTEXT 29 -#define NLF_FILE_ERROR 30 -#define NLF_CANT_WRITE 31 -#define NLF_COPY_FAILED 32 -#define NLF_COPY_TO 33 -#define NLF_SYMBOL_NOT_FOUND 34 -#define NLF_COULD_NOT_LOAD 35 -#define NLF_CREATE_DIR 36 -#define NLF_CREATE_SHORTCUT 37 -#define NLF_CREATED_UNINST 38 -#define NLF_DEL_FILE 39 -#define NLF_DEL_ON_REBOOT 40 -#define NLF_ERR_CREATING_SHORTCUT 41 -#define NLF_ERR_CREATING 42 -#define NLF_ERR_DECOMPRESSING 43 -#define NLF_ERR_REG_DLL 44 -#define NLF_EXEC_SHELL 45 -#define NLF_EXEC 46 -#define NLF_EXTRACT 47 -#define NLF_ERR_WRITING 48 -#define NLF_INST_CORRUPTED 49 -#define NLF_NO_OLE 50 -#define NLF_OUTPUT_DIR 51 -#define NLF_REMOVE_DIR 52 -#define NLF_RENAME_ON_REBOOT 53 -#define NLF_RENAME 54 -#define NLF_SKIPPED 55 -#define NLF_COPY_DETAILS 56 +enum { + NLF_BRANDING, + NLF_CAPTION, + NLF_UCAPTION, + NLF_SUBCAPTION_LICENSE, + NLF_SUBCAPTION_OPTIONS, + NLF_SUBCAPTION_DIR, + NLF_SUBCAPTION_INSTFILES, + NLF_SUBCAPTION_COMPLETED, + NLF_USUBCAPTION_CONFIRM, + NLF_USUBCAPTION_INSTFILES, + NLF_USUBCAPTION_COMPLETED, + NLF_BTN_BACK, + NLF_BTN_NEXT, + NLF_BTN_LICENSE, + NLF_BTN_INSTALL, + NLF_BTN_UNINSTALL, + NLF_BTN_CANCEL, + NLF_BTN_CLOSE, + NLF_BTN_BROWSE, + NLF_BTN_DETAILS, + NLF_DEF_NAME, + NLF_COMPLETED, + NLF_COMP_CUSTOM, + NLF_COMP_SUBTEXT1, + NLF_COMP_SUBTEXT1_NO_INST_TYPES, + NLF_COMP_SUBTEXT2, + NLF_DIR_SUBTEXT, + NLF_SPACE_AVAIL, + NLF_SPACE_REQ, + NLF_UNINST_SUBTEXT, + NLF_FILE_ERROR, + NLF_CANT_WRITE, + NLF_COPY_FAILED, + NLF_COPY_TO, + NLF_SYMBOL_NOT_FOUND, + NLF_COULD_NOT_LOAD, + NLF_CREATE_DIR, + NLF_CREATE_SHORTCUT, + NLF_CREATED_UNINST, + NLF_DEL_FILE, + NLF_DEL_ON_REBOOT, + NLF_ERR_CREATING_SHORTCUT, + NLF_ERR_CREATING, + NLF_ERR_DECOMPRESSING, + NLF_ERR_REG_DLL, + NLF_EXEC_SHELL, + NLF_EXEC, + NLF_EXTRACT, + NLF_ERR_WRITING, + NLF_INST_CORRUPTED, + NLF_NO_OLE, + NLF_OUTPUT_DIR, + NLF_REMOVE_DIR, + NLF_RENAME_ON_REBOOT, + NLF_RENAME, + NLF_SKIPPED, + NLF_COPY_DETAILS, -#define LANG_NAME 102 -#define LANG_COMP_TEXT 103 -#define LANG_LICENSE_TEXT 104 -#define LANG_LICENSE_DATA 105 -#define LANG_DIR_TEXT 106 -#define LANG_UNINST_TEXT 107 + LANG_NAME, + LANG_COMP_TEXT, + LANG_LICENSE_TEXT, + LANG_LICENSE_DATA, + LANG_DIR_TEXT, + LANG_UNINST_TEXT +}; extern char *english_strings[NLF_STRINGS]; diff --git a/Source/script.cpp b/Source/script.cpp index 7db4ed9a..b20ef638 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -506,6 +506,176 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char } return PS_OK; + // page ordering shit + /////////////////////////////////////////////////////////////////////////////// + case TOK_PAGE: + { + SCRIPT_MSG("Page: %s", line.gettoken_str(1)); + + int k = line.gettoken_enum(1,"custom\0license\0components\0directory\0instfiles"); + page p = { + 0, +#ifdef NSIS_SUPPORT_CODECALLBACKS + -1, + -1 +#endif + }; + + if (line.getnumtokens()>2) { +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (*line.gettoken_str(2)) + p.prefunc = ns_func.add(line.gettoken_str(2),0); + if (line.getnumtokens()>3) { + if (k==0) { + ERROR_MSG("\nError: custom page don't need post creation functions!\n"); + PRINTHELP(); + } + p.postfunc = ns_func.add(line.gettoken_str(3),0); + } +#else + ERROR_MSG("Error: Page callback specified, NSIS_CONFIG_LICENSEPAGE not defined.\n"); + return PS_ERROR; +#endif + } + else if (k==0) { + ERROR_MSG("\nError: custom page must have a creator function!\n"); + PRINTHELP(); + } + + switch (k) { + case 0: + p.id = NSIS_PAGE_CUSTOM; + break; + case 1: +#ifdef NSIS_CONFIG_LICENSEPAGE + p.id = NSIS_PAGE_LICENSE; + break; +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_LICENSEPAGE not defined.\n", line.gettoken_str(1)); + return PS_ERROR; +#endif + case 2: +#ifdef NSIS_CONFIG_COMPONENTPAGE + p.id = NSIS_PAGE_SELCOM; + break; +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_COMPONENTPAGE not defined.\n", line.gettoken_str(1)); + return PS_ERROR; +#endif + case 3: + p.id = NSIS_PAGE_DIR; + break; + case 4: + p.id = NSIS_PAGE_INSTFILES; + break; + default: + PRINTHELP(); + } + +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (p.prefunc>=0) + SCRIPT_MSG(" (%s:%s)", k?"pre":"creator", line.gettoken_str(2)); + if (p.postfunc>=0) + SCRIPT_MSG(" (post:%s)", line.gettoken_str(3)); +#endif + SCRIPT_MSG("\n"); + + build_pages.add(&p,sizeof(page)); + build_header.common.num_pages++; + if (p.id==NSIS_PAGE_INSTFILES) { + p.id=NSIS_PAGE_COMPLETED; +#ifdef NSIS_SUPPORT_CODECALLBACKS + p.prefunc=-1; + p.postfunc=-1; +#endif + build_pages.add(&p,sizeof(page)); + build_header.common.num_pages++; + } + } + return PS_OK; + case TOK_UNINSTPAGE: +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + { + SCRIPT_MSG("UninstPage: %s", line.gettoken_str(1)); + + int k = line.gettoken_enum(1,"custom\0uninstConfirm\0instfiles"); + page p = { + 0, +#ifdef NSIS_SUPPORT_CODECALLBACKS + -1, + -1 +#endif + }; + + if (line.getnumtokens()>2) { +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (*line.gettoken_str(2)) { + if (strnicmp(line.gettoken_str(2),"un.",3)) { + ERROR_MSG("\nError: function must have a un. prefix!\n"); + return PS_ERROR; + } + p.prefunc = ns_func.add(line.gettoken_str(2),0); + } + if (line.getnumtokens()>3) { + if (k==0) { + ERROR_MSG("\nError: custom page don't need post creation functions!\n"); + PRINTHELP(); + } + if (strnicmp(line.gettoken_str(3),"un.",3)) { + ERROR_MSG("\nError: function must have a un. prefix!\n"); + return PS_ERROR; + } + p.postfunc = ns_func.add(line.gettoken_str(3),0); + } +#else + ERROR_MSG("Error: UninstPage callback specified, NSIS_CONFIG_LICENSEPAGE not defined.\n"); + return PS_ERROR; +#endif + } + else if (k==0) { + ERROR_MSG("\nError: custom page must have a creator function!\n"); + PRINTHELP(); + } + + switch (k) { + case 0: + p.id = NSIS_PAGE_CUSTOM; + break; + case 1: + p.id = NSIS_PAGE_UNINST; + break; + case 2: + p.id = NSIS_PAGE_INSTFILES; + break; + default: + PRINTHELP(); + } + +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (p.prefunc>=0) + SCRIPT_MSG(" (%s:%s)", k?"pre":"creator", line.gettoken_str(2)); + if (p.postfunc>=0) + SCRIPT_MSG(" (post:%s)", line.gettoken_str(3)); +#endif + SCRIPT_MSG("\n"); + + ubuild_pages.add(&p,sizeof(page)); + build_uninst.common.num_pages++; + if (p.id==NSIS_PAGE_INSTFILES) { + p.id=NSIS_PAGE_COMPLETED; +#ifdef NSIS_SUPPORT_CODECALLBACKS + p.prefunc=-1; + p.postfunc=-1; +#endif + ubuild_pages.add(&p,sizeof(page)); + build_uninst.common.num_pages++; + } + } + return PS_OK; +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif // header flags /////////////////////////////////////////////////////////////////////////////// case TOK_LANGSTRING: @@ -1591,7 +1761,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char case TOK_UNINSTICON: case TOK_UNINSTTEXT: case TOK_UNINSTSUBCAPTION: - ERROR_MSG("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n", line.gettoken_str(0)); + ERROR_MSG("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n", line.gettoken_str(0)); return PS_ERROR; #endif diff --git a/Source/tokens.cpp b/Source/tokens.cpp index 6abad57e..91655cf4 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -61,7 +61,7 @@ static tokenType tokenlist[TOK__LAST] = {TOK_FINDCLOSE,"FindClose",1,0,"$(user_var: handle input)"}, {TOK_FINDFIRST,"FindFirst",3,0,"$(user_var: handle output) $(user_var: filename output) filespec"}, {TOK_FINDNEXT,"FindNext",2,0,"$(user_var: handle input) $(user_var: filename output)"}, -{TOK_FILE,"File",1,-1,"[/nonfatal] ([/a] [/r] filespec [...]|/oname=outfile one_file_only)"}, +{TOK_FILE,"File",1,-1,"[/nonfatal] [/a] ([/r] filespec [...]|/oname=outfile one_file_only)"}, {TOK_RESERVEFILE,"ReserveFile",1,-1,"[/nonfatal] [/r] file [file...]"}, {TOK_FILECLOSE,"FileClose",1,0,"$(user_var: handle input)"}, {TOK_FILEERRORTEXT,"FileErrorText",0,2,"[/LANG=lang_id] [text (can contain $0)]"}, @@ -105,6 +105,7 @@ static tokenType tokenlist[TOK__LAST] = {TOK_NOP,"Nop",0,0,""}, {TOK_NAME,"Name",1,1,"[/LANG=lang_id] installer_name"}, {TOK_OUTFILE,"OutFile",1,0,"install_output.exe"}, +{TOK_PAGE,"Page",1,2,"custom function | (license|components|directory|instfiles) [pre_function] [post_function]"}, {TOK_POP,"Pop",1,0,"$(user_var: output)"}, {TOK_PUSH,"Push",1,0,"string"}, {TOK_QUIT,"Quit",0,0,""}, @@ -154,9 +155,10 @@ static tokenType tokenlist[TOK__LAST] = {TOK_STRLEN,"StrLen",2,0,"$(user_var: length output) str"}, {TOK_SUBCAPTION,"SubCaption",2,1,"[/LANG=lang_id] page_number(0-4) new_subcaption"}, {TOK_UNINSTALLEXENAME,"UninstallExeName",0,0,"no longer supported, use WriteUninstaller from section."}, -{TOK_UNINSTICON,"UninstallIcon",1,0,"icon_on_local_system.ico"}, -{TOK_UNINSTTEXT,"UninstallText",1,2,"[/LANG=lang_id] Text_to_go_on_uninstall page [subtext]"}, {TOK_UNINSTCAPTION,"UninstallCaption",1,1,"[/LANG=lang_id] uninstaller_caption"}, +{TOK_UNINSTICON,"UninstallIcon",1,0,"icon_on_local_system.ico"}, +{TOK_UNINSTPAGE,"UninstPage",1,2,"custom function | (uninstConfirm|instfiles) [pre_function] [post_function]"}, +{TOK_UNINSTTEXT,"UninstallText",1,2,"[/LANG=lang_id] Text_to_go_on_uninstall page [subtext]"}, {TOK_UNINSTSUBCAPTION,"UninstallSubCaption",2,1,"[/LANG=lang_id] page_number(0-2) new_subcaption"}, {TOK_UNREGDLL,"UnRegDLL",1,0,"dll_path_on_target.dll"}, // useless - {TOK_USEOUTERUIITEM,"UseOuterUIItem",2,0,"item id"}, diff --git a/Source/tokens.h b/Source/tokens.h index 68366629..dc2609ea 100644 --- a/Source/tokens.h +++ b/Source/tokens.h @@ -87,6 +87,10 @@ enum TOK_FUNCTIONEND, TOK_ADDSIZE, + // Page oredering shit + TOK_PAGE, + TOK_UNINSTPAGE, + // flag setters TOK_SETDATESAVE, TOK_SETOVERWRITE,