diff --git a/Contrib/InstallOptions/Changelog.txt b/Contrib/InstallOptions/Changelog.txt
index 27da03f5..79c20011 100644
--- a/Contrib/InstallOptions/Changelog.txt
+++ b/Contrib/InstallOptions/Changelog.txt
@@ -1,3 +1,9 @@
+DLL version 2.3 (12/4/2003)
+* Added new control type "Button"
+* Added new flag "NOTIFY"
+* Added new flag "NOWORDWRAP" for multi-line text boxes
+* Reduced size down to 12K
+
DLL version 2.2 (6/10/2003)
* Added New control type LINK
* \r\n converts to newline in Multiline edit box
@@ -24,45 +30,45 @@ DLL version 2.0 (1/4/2003)
* New documentation (by Joost Verburg)
* New GROUP/NOTABSTOP/DISABLED flags
-DLL version 1.7 beta (11/2/2002)
+DLL version 1.7 beta (11/2/2002)
* Added initDialog and show DLL functions
DLL version 1.6 beta (9/30/2002)
* CancelConfirmIcon becomes CancelConfirmFlags and can now take the other common MessageBox flags
-DLL version 1.5 beta (9/26/2002)
+DLL version 1.5 beta (9/26/2002)
* Made close [x] button behave like Cancel (thanks brainsucker)
DLL version 1.4 beta (9/4/2002)
* Added Icon and Bitmap controls (by Amir Szekely)
DLL version 1.3 beta (8/15/2002)
-* Added CancelShow (by ORTIM)
+* Added CancelShow (by ORTIM)
* Added pixel transformation for widgets (by ORTIM)
DLL version 1.2 beta (7/31/2002)
* Added CancelEnabled (by ORTIM)
-* Added CancelConfirmCaption and CancelConfirmIcon (by Amir Szekely)
+* Added CancelConfirmCaption and CancelConfirmIcon (by Amir Szekely)
DLL version 1.1 beta (7/22/2002)
* Font is now taken from the main NSIS window (by Amir Szekely)
DLL version 1.0 beta (12/16/2001)
-* Moved to DLL, no longer need parentwnd ini writing
-* Tons of changes - no longer fully compatible (see source for a big list)
-* removed support for silent installers (it seems the old version would bring up it's own dialog)
+* Moved to DLL, no longer need parentwnd ini writing
+* Tons of changes - no longer fully compatible (see source for a big list)
+* removed support for silent installers (it seems the old version would bring up it's own dialog)
version 1.4 (11/18/2001)
-* Added Listbox controls.
-* Added MULTISELECT flag.
+* Added Listbox controls.
+* Added MULTISELECT flag.
* Made the HWND list for the parent window controls dynamically allocated. This prevents a crash if NSIS ever gets more than 150 controls on it's main window.
-* The TEXT property of DirRequest control can be used to specify an initial directory. The current directory is automatically selected when clicking the browse button of the DirRequest control.
-* Added ROOT property to DirRequest which can be used to set the root directory (mostly due to felfert)
-* Edit controls will now auto scroll (thanks felfert)
-* Fixed a problem where the window wouldn't draw properly on some systems (thanks felfert)
+* The TEXT property of DirRequest control can be used to specify an initial directory. The current directory is automatically selected when clicking the browse button of the DirRequest control.
+* Added ROOT property to DirRequest which can be used to set the root directory (mostly due to felfert)
+* Edit controls will now auto scroll (thanks felfert)
+* Fixed a problem where the window wouldn't draw properly on some systems (thanks felfert)
version 1.3 (11/03/2001)
-* Got rid of the call to RedrawWindow() because it's no longer needed with the WS_CLIPCHILDREN flag for NSIS.
+* Got rid of the call to RedrawWindow() because it's no longer needed with the WS_CLIPCHILDREN flag for NSIS.
* Removed a few hardcoded limits of buffer sizes
* Added Checkbox and RadioButton controls
* Added RIGHT and CHECKED flags
@@ -71,10 +77,10 @@ version 1.2.2 (10/30/2001)
* Additional size reductions. Further reduced the size down to 8k.
* The text parameter to a combobox can now be used to specify the initial value
* Changed from InvalidateRect() to RedrawWindow() to force a redraw after a browse dialog
-* On startup, set the flags of the NSIS window to include WS_CLIPCHILDREN. Otherwise, our controls don't get drawn right.
+* On startup, set the flags of the NSIS window to include WS_CLIPCHILDREN. Otherwise, our controls don't get drawn right.
version 1.2.1 (10/28/2001)
-* Bug fix. ControlID for the caption and the OK button were reused by the first two controls. (Thanks Schultz)
+* Bug fix. ControlID for the caption and the OK button were reused by the first two controls. (Thanks Schultz)
version 1.2j (10/28/2001)
* 8.5kb from 44kb. heh. (by Justin Frankel)
@@ -98,4 +104,4 @@ version 1.01 (10/25/2001)
* Added the license to the documentation
version 1.0 (10/25/2001)
-* Barely qualifies as a distribution
\ No newline at end of file
+* Barely qualifies as a distribution
diff --git a/Contrib/InstallOptions/InstallerOptions.cpp b/Contrib/InstallOptions/InstallerOptions.cpp
index f5ac491c..23ab8f17 100644
--- a/Contrib/InstallOptions/InstallerOptions.cpp
+++ b/Contrib/InstallOptions/InstallerOptions.cpp
@@ -18,6 +18,9 @@
#include "../exdll/exdll.h"
#undef popstring
+void *WINAPI MALLOC(int len) { return (void*)GlobalAlloc(GPTR,len); }
+void WINAPI FREE(void *d) { if (d) GlobalFree((HGLOBAL)d); }
+
static int WINAPI popstring(char *str)
{
stack_t *th;
@@ -25,7 +28,7 @@ static int WINAPI popstring(char *str)
th=(*g_stacktop);
if (str) lstrcpy(str,th->text);
*g_stacktop = th->next;
- GlobalFree((HGLOBAL)th);
+ FREE(th);
return 0;
}
@@ -41,14 +44,11 @@ typedef struct {
} ctlcolors;
#define strcpy(x,y) lstrcpy(x,y)
-#define strncpy(x,y,z) lstrcpyn(x,y,z)
+//#define strncpy(x,y,z) lstrcpyn(x,y,z)
#define strdup(x) STRDUP(x)
#define stricmp(x,y) lstrcmpi(x,y)
//#define abs(x) ((x) < 0 ? -(x) : (x))
-void *WINAPI MALLOC(int len) { return (void*)GlobalAlloc(GPTR,len); }
-void WINAPI FREE(void *d) { if (d) GlobalFree((HGLOBAL)d); }
-
char *WINAPI STRDUP(const char *c)
{
char *t=(char*)MALLOC(lstrlen(c)+1);
@@ -69,6 +69,7 @@ char *WINAPI STRDUP(const char *c)
#define FIELD_LISTBOX (11)
#define FIELD_GROUPBOX (12)
#define FIELD_LINK (13)
+#define FIELD_BUTTON (14)
//---------------------------------------------------------------------
// settings
@@ -107,6 +108,15 @@ char *WINAPI STRDUP(const char *c)
// bitmap flags
#define FLAG_RESIZETOFIT 0x00008000
+// general flags
+#define FLAG_NOTIFY 0x00010000 // Notify NSIS script when control is "activated" (exact meaning depends on the type of control)
+
+// browse flags
+#define FLAG_SAVEAS 0x00020000 // Show "Save As" instead of "Open" for FileRequest field
+
+// text box flags
+#define FLAG_NOWORDWRAP 0x00040000 // Disable word-wrap in multi-line text boxes
+
// OFN_EXPLORER 0x00080000
// more text box flags
@@ -141,12 +151,11 @@ struct FieldType {
char *pszValidateText;
int nFlags;
- bool bSaveDlg;
HWND hwnd;
UINT nControlID;
- int nParentIdx; // this is used by the filerequest and dirrequest controls, used to store original windowproc for LINK
+ int nParentIdx; // this is used to store original windowproc for LINK
HANDLE hImage; // this is used by image/icon field to save the handle to the image
};
@@ -184,6 +193,7 @@ FieldType *pFields = NULL;
int nRectId = 0;
int nNumFields = 0;
int g_done;
+int g_NotifyField; // Field number of notifying control
int WINAPI FindControlIdx(UINT id)
{
@@ -193,124 +203,24 @@ int WINAPI FindControlIdx(UINT id)
return -1;
}
-// array of HWNDs and window styles used to make the main NSIS controls invisible while this program runs.
-
-bool WINAPI BrowseForFile(int nControlIdx) {
- OPENFILENAME ofn={0,};
- HWND hControl;
- BOOL bResult;
- FieldType *pThisField = &pFields[nControlIdx];
-
- hControl = pThisField->hwnd;
-
- ofn.Flags = pThisField->nFlags & (OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_CREATEPROMPT | OFN_EXPLORER);
-
-// ofn.hInstance = m_hInstance; // no templates so we can leave this at NULL;
- ofn.hwndOwner = hConfigWindow;
-// ofn.lCustData = NULL;
-// ofn.lpfnHook = NULL;
-// ofn.lpstrCustomFilter = NULL;
-// ofn.lpstrDefExt = NULL;
- ofn.nMaxFile = MAX_PATH;
- ofn.lpstrFile = (char*)MALLOC(MAX_PATH);
-
-// ofn.nMaxFileTitle = MAX_PATH; // we ignore this for simplicity, leave lpstrFileTitle at NULL
-// ofn.lpstrFileTitle = new char [ofn.nMaxFileTitle];
-
- ofn.lpstrFilter = pThisField->pszFilter; // TODO: implement this
-// ofn.lpstrInitialDir = NULL; // for now, just use the default initial directory.
-// ofn.lpstrTitle = NULL; // TODO: implement this
-// ofn.lpTemplateName = NULL;
- ofn.lStructSize = sizeof(ofn);
-// ofn.nFileExtension // this is output variable, leave it to 0 for now.
-// ofn.nFileOffset // this is output variable, leave it to 0 for now.
-// ofn.nFilterIndex = 1; // since we use no custom filters, leaving it at 0 means use the first.
-// ofn.nMaxCustFilter = 0;
-
- GetWindowText(hControl, ofn.lpstrFile, MAX_PATH);
-
-tryagain:
- if (pThisField->bSaveDlg) {
- bResult = GetSaveFileName(&ofn);
- } else {
- bResult = GetOpenFileName(&ofn);
- }
- if (bResult) {
- SetWindowText(hControl, ofn.lpstrFile);
- return true;
- }
- else if (ofn.lpstrFile[0] && CommDlgExtendedError() == FNERR_INVALIDFILENAME) {
- ofn.lpstrFile[0] = '\0';
- goto tryagain;
- }
-
- return false;
+LRESULT WINAPI mySendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ return SendMessage(hWnd, Msg, wParam, lParam);
}
int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData) {
- TCHAR szDir[MAX_PATH];
+ static TCHAR szDir[MAX_PATH];
if (uMsg == BFFM_INITIALIZED) {
if (GetWindowText(pFields[(int)pData].hwnd, szDir, MAX_PATH) > 0) {
- SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szDir);
+ mySendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szDir);
}
}
return 0;
}
-bool WINAPI BrowseForFolder(int nControlIdx) {
- BROWSEINFO bi;
-
- bi.hwndOwner = hConfigWindow;
- bi.pidlRoot = NULL;
- bi.pszDisplayName = (char*)MALLOC(MAX_PATH);
- bi.lpszTitle = pFields[nControlIdx].pszText;
-#ifndef BIF_NEWDIALOGSTYLE
-#define BIF_NEWDIALOGSTYLE 0x0040
-#endif
- bi.ulFlags = BIF_STATUSTEXT | BIF_RETURNONLYFSDIRS| BIF_NEWDIALOGSTYLE;
- bi.lpfn = BrowseCallbackProc;
- bi.lParam = nControlIdx;
- bi.iImage = 0;
-
- if (pFields[nControlIdx].pszRoot) {
- LPSHELLFOLDER sf;
- ULONG eaten;
- LPITEMIDLIST root;
- int ccRoot = (lstrlen(pFields[nControlIdx].pszRoot) * 2) + 2;
- LPWSTR pwszRoot = (LPWSTR) MALLOC(ccRoot);
- MultiByteToWideChar(CP_ACP, 0, pFields[nControlIdx].pszRoot, -1, pwszRoot, ccRoot);
- SHGetDesktopFolder(&sf);
- sf->ParseDisplayName(hConfigWindow, NULL, pwszRoot, &eaten, &root, NULL);
- bi.pidlRoot = root;
- sf->Release();
- FREE(pwszRoot);
- }
-// CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
- LPITEMIDLIST pResult = SHBrowseForFolder(&bi);
- if (!pResult) {
- FREE(bi.pszDisplayName);
- return false;
- }
-
- char *pszFolder = (char*)MALLOC(MAX_PATH);
- if (SHGetPathFromIDList(pResult, pszFolder)) {
- SetWindowText(pFields[nControlIdx].hwnd, pszFolder);
- }
-
- LPMALLOC pMalloc;
- if (!SHGetMalloc(&pMalloc)) {
- pMalloc->Free(pResult);
- }
-
- FREE(bi.pszDisplayName);
- FREE(pszFolder);
-
- return true;
-}
-
bool WINAPI ValidateFields() {
int nIdx;
int nLength;
@@ -318,17 +228,18 @@ bool WINAPI ValidateFields() {
// In the unlikely event we can't allocate memory, go ahead and return true so we can get out of here.
// May cause problems for the install script, but no memory is problems for us.
for (nIdx = 0; nIdx < nNumFields; nIdx++) {
+ FieldType *pField = pFields + nIdx;
// 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 = SendMessage(pFields[nIdx].hwnd, WM_GETTEXTLENGTH, 0, 0);
+ if (pField->nType >= FIELD_TEXT) {
+ nLength = mySendMessage(pField->hwnd, WM_GETTEXTLENGTH, 0, 0);
- if (((pFields[nIdx].nMaxLength > 0) && (nLength > pFields[nIdx].nMaxLength)) ||
- ((pFields[nIdx].nMinLength > 0) && (nLength < pFields[nIdx].nMinLength))) {
- if (pFields[nIdx].pszValidateText) {
- MessageBox(hConfigWindow, pFields[nIdx].pszValidateText, NULL, MB_OK|MB_ICONWARNING);
+ if (((pField->nMaxLength > 0) && (nLength > pField->nMaxLength)) ||
+ ((pField->nMinLength > 0) && (nLength < pField->nMinLength))) {
+ if (pField->pszValidateText) {
+ MessageBox(hConfigWindow, pField->pszValidateText, NULL, MB_OK|MB_ICONWARNING);
}
- SetFocus(pFields[nIdx].hwnd);
+ SetFocus(pField->hwnd);
return false;
}
@@ -340,27 +251,28 @@ bool WINAPI ValidateFields() {
bool WINAPI SaveSettings(void) {
static char szField[25];
int nIdx;
- HWND hwnd;
int nBufLen = MAX_BUFFER_LENGTH;
char *pszBuffer = (char*)MALLOC(nBufLen);
if (!pszBuffer) return false;
int CurrField = 1;
- for(nIdx = 0; nIdx < nNumFields; nIdx++) {
- if (pFields[nIdx].nType == FIELD_BROWSEBUTTON)
- continue;
-
- hwnd = pFields[nIdx].hwnd;
- wsprintf(szField, "Field %d", CurrField);
- switch(pFields[nIdx].nType) {
+ for (nIdx = 0; nIdx < nNumFields; nIdx++) {
+ FieldType *pField = pFields + nIdx;
+ HWND hwnd = pField->hwnd;
+ switch (pField->nType) {
+ case FIELD_BROWSEBUTTON:
+ if (g_NotifyField > CurrField)
+ --g_NotifyField;
+ continue;
case FIELD_INVALID:
+ case FIELD_LABEL:
+ case FIELD_BUTTON:
+ *pszBuffer=0;
break;
case FIELD_CHECKBOX:
case FIELD_RADIOBUTTON:
- {
- wsprintf(pszBuffer, "%d", !!SendMessage(hwnd, BM_GETCHECK, 0, 0));
- break;
- }
+ wsprintf(pszBuffer, "%d", !!mySendMessage(hwnd, BM_GETCHECK, 0, 0));
+ break;
case FIELD_LISTBOX:
{
// Ok, this one requires a bit of work.
@@ -368,7 +280,7 @@ bool WINAPI SaveSettings(void) {
// Then, we loop through every item and if it's selected we add it to our buffer.
// If there is already an item in the list, then we prepend a | character before the new item.
// We could simplify for single-select boxes, but using one piece of code saves some space.
- int nLength = lstrlen(pFields[nIdx].pszListItems) + 10;
+ int nLength = lstrlen(pField->pszListItems) + 10;
if (nLength > nBufLen) {
FREE(pszBuffer);
nBufLen = nLength;
@@ -379,11 +291,11 @@ bool WINAPI SaveSettings(void) {
if (!pszItem) return false;
*pszBuffer = '\0';
- int nNumItems = SendMessage(hwnd, LB_GETCOUNT, 0, 0);
- for(int nIdx2 = 0; nIdx2 < nNumItems; nIdx2++) {
- if (SendMessage(hwnd, LB_GETSEL, nIdx2, 0) > 0) {
+ int nNumItems = mySendMessage(hwnd, LB_GETCOUNT, 0, 0);
+ for (int nIdx2 = 0; nIdx2 < nNumItems; nIdx2++) {
+ if (mySendMessage(hwnd, LB_GETSEL, nIdx2, 0) > 0) {
if (*pszBuffer) lstrcat(pszBuffer, "|");
- SendMessage(hwnd, LB_GETTEXT, (WPARAM)nIdx2, (LPARAM)pszItem);
+ mySendMessage(hwnd, LB_GETTEXT, (WPARAM)nIdx2, (LPARAM)pszItem);
lstrcat(pszBuffer, pszItem);
}
}
@@ -391,12 +303,9 @@ bool WINAPI SaveSettings(void) {
FREE(pszItem);
break;
}
- case FIELD_LABEL:
- *pszBuffer=0;
- break;
default:
{
- int nLength = SendMessage(pFields[nIdx].hwnd, WM_GETTEXTLENGTH, 0, 0);
+ int nLength = mySendMessage(pField->hwnd, WM_GETTEXTLENGTH, 0, 0);
if (nLength > nBufLen) {
FREE(pszBuffer);
// add a bit extra so we do this less often
@@ -409,7 +318,7 @@ bool WINAPI SaveSettings(void) {
pszBuffer[nLength+1]='"';
pszBuffer[nLength+2]='\0';
- if ( pFields[nIdx].nType == FIELD_TEXT && pFields[nIdx].nFlags & FLAG_MULTILINE )
+ if ( pField->nType == FIELD_TEXT && pField->nFlags & FLAG_MULTILINE )
{
char *pszBuf2 = (char*)MALLOC(nBufLen*2); // double the size, consider the worst case, all chars are \r\n
char *p1, *p2;
@@ -442,10 +351,15 @@ bool WINAPI SaveSettings(void) {
break;
}
}
- WritePrivateProfileString(szField, "STATE", pszBuffer, pszFilename);
+ wsprintf(szField, "Field %d", CurrField);
+ WritePrivateProfileString(szField, "State", pszBuffer, pszFilename);
CurrField++;
}
+ // Tell NSIS which control was activated, if any
+ wsprintf(pszBuffer, "%d", g_NotifyField);
+ WritePrivateProfileString("Settings", "State", pszBuffer, pszFilename);
+
FREE(pszBuffer);
return true;
@@ -503,7 +417,7 @@ int WINAPI ReadSettings(void) {
pFields = (FieldType *)MALLOC(sizeof(FieldType)*2*nNumFields);
}
- for(nIdx = 0, nCtrlIdx = 0; nCtrlIdx < nNumFields; nCtrlIdx++, nIdx++) {
+ for (nIdx = 0, nCtrlIdx = 0; nCtrlIdx < nNumFields; nCtrlIdx++, nIdx++) {
// Control types
static TableEntry TypeTable[] = {
{ "LABEL", FIELD_LABEL },
@@ -524,87 +438,92 @@ int WINAPI ReadSettings(void) {
#else
{ "LINK", FIELD_LABEL },
#endif
+ { "BUTTON", FIELD_BUTTON },
{ NULL, 0 }
};
// Control flags
static TableEntry FlagTable[] = {
- { "FILE_MUST_EXIST", OFN_FILEMUSTEXIST },
- { "PATH_MUST_EXIST", OFN_PATHMUSTEXIST },
- { "WARN_IF_EXIST", OFN_OVERWRITEPROMPT },
- { "PROMPT_CREATE", OFN_CREATEPROMPT },
{ "RIGHT", FLAG_RIGHT },
- { "PASSWORD", FLAG_PASSWORD },
- { "DROPLIST", FLAG_DROPLIST },
- { "MULTISELECT", FLAG_MULTISELECT },
- { "EXTENDEDSELCT", FLAG_EXTENDEDSEL },
- { "FILE_EXPLORER", OFN_EXPLORER },
+ { "WARN_IF_EXIST", OFN_OVERWRITEPROMPT },
{ "FILE_HIDEREADONLY", OFN_HIDEREADONLY },
- { "RESIZETOFIT", FLAG_RESIZETOFIT },
- { "GROUP", FLAG_GROUP },
{ "DISABLED", FLAG_DISABLED },
+ { "GROUP", FLAG_GROUP },
{ "NOTABSTOP", FLAG_NOTABSTOP },
+ { "PASSWORD", FLAG_PASSWORD },
{ "ONLY_NUMBERS", FLAG_ONLYNUMBERS },
{ "MULTILINE", FLAG_MULTILINE },
+ { "MULTISELECT", FLAG_MULTISELECT },
+ { "EXTENDEDSELCT", FLAG_EXTENDEDSEL },
+ { "FILE_MUST_EXIST", OFN_FILEMUSTEXIST },
+ { "PATH_MUST_EXIST", OFN_PATHMUSTEXIST },
+ { "PROMPT_CREATE", OFN_CREATEPROMPT },
+ { "DROPLIST", FLAG_DROPLIST },
+ { "RESIZETOFIT", FLAG_RESIZETOFIT },
+ { "NOTIFY", FLAG_NOTIFY },
+ { "REQ_SAVE", FLAG_SAVEAS },
+ { "NOWORDWRAP", FLAG_NOWORDWRAP },
+ { "FILE_EXPLORER", OFN_EXPLORER },
+ { "WANTRETURN", FLAG_WANTRETURN },
{ "VSCROLL", FLAG_VSCROLL },
{ "HSCROLL", FLAG_HSCROLL },
- { "WANTRETURN", FLAG_WANTRETURN },
{ "READONLY", FLAG_READONLY },
{ NULL, 0 }
};
+ FieldType *pField = pFields + nIdx;
wsprintf(szField, "Field %d", nCtrlIdx + 1);
myGetProfileString(szField, "TYPE");
// Get the control type
- pFields[nIdx].nType = LookupToken(TypeTable, szResult);
- if (pFields[nIdx].nType == FIELD_INVALID)
+ pField->nType = LookupToken(TypeTable, szResult);
+ if (pField->nType == FIELD_INVALID)
continue;
// Lookup flags associated with the control type
- pFields[nIdx].nFlags |= LookupToken(FlagTable, szResult);
+ pField->nFlags |= LookupToken(FlagTable, szResult);
- pFields[nIdx].pszText = myGetProfileStringDup(szField, "TEXT");
+ pField->pszText = myGetProfileStringDup(szField, "TEXT");
// Label Text - convert newline
- if (pFields[nIdx].nType == FIELD_LABEL) {
- ConvertNewLines(pFields[nIdx].pszText);
+ if (pField->nType == FIELD_LABEL) {
+ ConvertNewLines(pField->pszText);
}
// pszState must not be NULL!
- myGetProfileString(szField, "STATE");
- pFields[nIdx].pszState = strdup(szResult);
+ myGetProfileString(szField, "State");
+ pField->pszState = strdup(szResult);
- pFields[nIdx].pszRoot = myGetProfileStringDup(szField, "ROOT");
+ pField->pszRoot = myGetProfileStringDup(szField, "ROOT");
{
int nResult = myGetProfileString(szField, "ListItems");
if (nResult) {
// add an extra | character to the end to simplify the loop where we add the items.
- pFields[nIdx].pszListItems = (char*)MALLOC(nResult + 2);
- strcpy(pFields[nIdx].pszListItems, szResult);
- pFields[nIdx].pszListItems[nResult] = '|';
- pFields[nIdx].pszListItems[nResult + 1] = '\0';
+ pField->pszListItems = (char*)MALLOC(nResult + 2);
+ strcpy(pField->pszListItems, szResult);
+ pField->pszListItems[nResult] = '|';
+ pField->pszListItems[nResult + 1] = '\0';
}
}
- pFields[nIdx].nMaxLength = myGetProfileInt(szField, "MaxLen", 0);
- pFields[nIdx].nMinLength = myGetProfileInt(szField, "MinLen", 0);
+ pField->nMaxLength = myGetProfileInt(szField, "MaxLen", 0);
+ pField->nMinLength = myGetProfileInt(szField, "MinLen", 0);
- pFields[nIdx].pszValidateText = myGetProfileStringDup(szField, "ValidateText");
+ pField->pszValidateText = myGetProfileStringDup(szField, "ValidateText");
// ValidateText - convert newline
- if (pFields[nIdx].pszValidateText) {
- ConvertNewLines(pFields[nIdx].pszValidateText);
+ if (pField->pszValidateText) {
+ ConvertNewLines(pField->pszValidateText);
}
{
int nResult = GetPrivateProfileString(szField, "Filter", "All Files|*.*", szResult, sizeof(szResult), pszFilename);
if (nResult) {
// add an extra | character to the end to simplify the loop where we add the items.
- pFields[nIdx].pszFilter = (char*)MALLOC(nResult + 2);
- strcpy(pFields[nIdx].pszFilter, szResult);
- char *pszPos = pFields[nIdx].pszFilter;
+ pField->pszFilter = (char*)MALLOC(nResult + 2);
+ strcpy(pField->pszFilter, szResult);
+ char *pszPos = pField->pszFilter;
while (*pszPos) {
if (*pszPos == '|') *pszPos = '\0';
pszPos++;
@@ -612,56 +531,31 @@ int WINAPI ReadSettings(void) {
}
}
- pFields[nIdx].rect.left = myGetProfileInt(szField, "LEFT", 0);
- pFields[nIdx].rect.right = myGetProfileInt(szField, "RIGHT", 0);
- pFields[nIdx].rect.top = myGetProfileInt(szField, "TOP", 0);
- pFields[nIdx].rect.bottom = myGetProfileInt(szField, "BOTTOM", 0);
+ pField->rect.left = myGetProfileInt(szField, "LEFT", 0);
+ pField->rect.right = myGetProfileInt(szField, "RIGHT", 0);
+ pField->rect.top = myGetProfileInt(szField, "TOP", 0);
+ pField->rect.bottom = myGetProfileInt(szField, "BOTTOM", 0);
- if (myGetProfileString(szField, "Flags")) {
- // append the | to make parsing a bit easier
- if (lstrlen(szResult) pszStart) {
- if (!stricmp("REQ_SAVE", pszStart)) {
- pFields[nIdx].bSaveDlg = true;
- } else {
- // v1.3 converted this to a table lookup.
- // I think it's a bit larger now, but we can
- // add new flags with very little overhead.
- pFields[nIdx].nFlags |= LookupToken(FlagTable, pszStart);
- }
- }
- // jump to the next item, skip any redundant | characters
- do { pszEnd++; } while (*pszEnd == '|');
- pszStart = pszEnd;
- }
- pszEnd++;
- }
- }
+ myGetProfileString(szField, "Flags");
+ pField->nFlags |= LookupTokens(FlagTable, szResult);
// Text color for LINK control, default is pure blue
- //if (pFields[nIdx].nType == FIELD_LINK)
- pFields[nIdx].hImage = (HANDLE)myGetProfileInt(szField, "TxtColor", RGB(0,0,255));
+ //if (pField->nType == FIELD_LINK)
+ pField->hImage = (HANDLE)myGetProfileInt(szField, "TxtColor", RGB(0,0,255));
- pFields[nIdx].nControlID = 1200 + nIdx;
- if (pFields[nIdx].nType == FIELD_FILEREQUEST || pFields[nIdx].nType == FIELD_DIRREQUEST)
+ pField->nControlID = 1200 + nIdx;
+ if (pField->nType == FIELD_FILEREQUEST || pField->nType == FIELD_DIRREQUEST)
{
FieldType *pNewField = &pFields[nIdx+1];
pNewField->nControlID = 1200 + nIdx + 1;
- pNewField->nParentIdx = nIdx;
pNewField->nType = FIELD_BROWSEBUTTON;
- pNewField->nFlags = pFields[nIdx].nFlags & (FLAG_DISABLED | FLAG_NOTABSTOP);
+ pNewField->nFlags = pField->nFlags & (FLAG_DISABLED | FLAG_NOTABSTOP);
pNewField->pszText = STRDUP(szBrowseButtonCaption); // needed for generic FREE
- pNewField->rect.right = pFields[nIdx].rect.right;
+ pNewField->rect.right = pField->rect.right;
pNewField->rect.left = pNewField->rect.right - BROWSE_WIDTH;
- pNewField->rect.bottom = pFields[nIdx].rect.bottom;
- pNewField->rect.top = pFields[nIdx].rect.top;
- pFields[nIdx].rect.right = pNewField->rect.left - 3;
+ pNewField->rect.bottom = pField->rect.bottom;
+ pNewField->rect.top = pField->rect.top;
+ pField->rect.right = pNewField->rect.left - 3;
nNumFields++;
nIdx++;
}
@@ -674,26 +568,97 @@ int WINAPI ReadSettings(void) {
LRESULT WINAPI WMCommandProc(HWND hWnd, UINT id, HWND hwndCtl, UINT codeNotify) {
switch (codeNotify) {
case BN_CLICKED:
- {
- int nIdx = FindControlIdx(id);
- if (nIdx < 0)
- break;
- if (pFields[nIdx].nType == FIELD_BROWSEBUTTON) {
- int nParentIdx = pFields[nIdx].nParentIdx;
- switch(pFields[nParentIdx].nType) {
- case FIELD_FILEREQUEST:
- BrowseForFile(nParentIdx);
- break;
- case FIELD_DIRREQUEST:
- BrowseForFolder(nParentIdx);
+ {
+ char szBrowsePath[MAX_PATH];
+ int nIdx = FindControlIdx(id);
+ if (nIdx < 0)
+ break;
+ if (pFields[nIdx].nType == FIELD_BROWSEBUTTON)
+ --nIdx;
+ FieldType *pField = pFields + nIdx;
+ switch (pField->nType) {
+ case FIELD_FILEREQUEST: {
+ OPENFILENAME ofn={0,};
+
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hConfigWindow;
+ ofn.lpstrFilter = pField->pszFilter;
+ ofn.lpstrFile = szBrowsePath;
+ ofn.nMaxFile = sizeof(szBrowsePath);
+ ofn.Flags = pField->nFlags & (OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_CREATEPROMPT | OFN_EXPLORER);
+
+ GetWindowText(pField->hwnd, szBrowsePath, sizeof(szBrowsePath));
+
+ tryagain:
+ if ((pField->nFlags & FLAG_SAVEAS) ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn)) {
+ SetWindowText(pField->hwnd, szBrowsePath);
break;
}
+ else if (szBrowsePath[0] && CommDlgExtendedError() == FNERR_INVALIDFILENAME) {
+ szBrowsePath[0] = '\0';
+ goto tryagain;
+ }
+
break;
- } else if (pFields[nIdx].nType == FIELD_LINK) {
- ShellExecute(hMainWindow, NULL, pFields[nIdx].pszState, NULL, NULL, SW_SHOWDEFAULT);
}
+
+ case FIELD_DIRREQUEST: {
+ BROWSEINFO bi;
+
+ bi.hwndOwner = hConfigWindow;
+ bi.pidlRoot = NULL;
+ bi.pszDisplayName = szBrowsePath;
+ bi.lpszTitle = pField->pszText;
+#ifndef BIF_NEWDIALOGSTYLE
+#define BIF_NEWDIALOGSTYLE 0x0040
+#endif
+ bi.ulFlags = BIF_STATUSTEXT | BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
+ bi.lpfn = BrowseCallbackProc;
+ bi.lParam = nIdx;
+ bi.iImage = 0;
+
+ if (pField->pszRoot) {
+ LPSHELLFOLDER sf;
+ ULONG eaten;
+ LPITEMIDLIST root;
+ int ccRoot = (lstrlen(pField->pszRoot) * 2) + 2;
+ LPWSTR pwszRoot = (LPWSTR) MALLOC(ccRoot);
+ MultiByteToWideChar(CP_ACP, 0, pField->pszRoot, -1, pwszRoot, ccRoot);
+ SHGetDesktopFolder(&sf);
+ sf->ParseDisplayName(hConfigWindow, NULL, pwszRoot, &eaten, &root, NULL);
+ bi.pidlRoot = root;
+ sf->Release();
+ FREE(pwszRoot);
+ }
+// CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+ LPITEMIDLIST pResult = SHBrowseForFolder(&bi);
+ if (!pResult)
+ break;
+
+ if (SHGetPathFromIDList(pResult, szBrowsePath)) {
+ SetWindowText(pField->hwnd, szBrowsePath);
+ }
+
+ LPMALLOC pMalloc;
+ if (!SHGetMalloc(&pMalloc)) {
+ pMalloc->Free(pResult);
+ }
+
+ break;
+ }
+
+ case FIELD_LINK:
+ ShellExecute(hMainWindow, NULL, pField->pszState, NULL, NULL, SW_SHOWDEFAULT);
+ break;
}
- break;
+
+ if (pField->nFlags & FLAG_NOTIFY) {
+ // Remember which control was activated then pretend the user clicked Next
+ g_NotifyField = nIdx + 1;
+ FORWARD_WM_COMMAND(hMainWindow, IDOK, hNextButton, codeNotify, mySendMessage);
+ }
+ }
+ break;
}
return 0;
}
@@ -710,6 +675,7 @@ BOOL CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPara
{
// Get the settings ready for the leave function verification
SaveSettings();
+ g_NotifyField = 0; // Reset the record of activated control
}
bRes = CallWindowProc((long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))lpWndProcOld,hwnd,message,wParam,lParam);
if (message == WM_NOTIFY_OUTER_NEXT && !bRes)
@@ -744,6 +710,7 @@ BOOL CALLBACK cfgDlgProc(HWND hwndDlg,
if (nIdx < 0)
break;
+ FieldType *pField = pFields + nIdx;
#ifdef IO_LINK_UNDERLINED
GetObject(GetCurrentObject(lpdis->hDC, OBJ_FONT), sizeof(lf), &lf);
@@ -757,24 +724,24 @@ BOOL CALLBACK cfgDlgProc(HWND hwndDlg,
if ( ( lpdis->itemState & ODS_FOCUS && lpdis->itemAction & ODA_DRAWENTIRE) || (lpdis->itemAction & ODA_FOCUS) ||
(lpdis->itemAction & ODA_SELECT))
- DrawFocusRect(lpdis->hDC, &pFields[nIdx].rect);
+ DrawFocusRect(lpdis->hDC, &pField->rect);
- SetTextColor(lpdis->hDC, (COLORREF)pFields[nIdx].hImage);
+ SetTextColor(lpdis->hDC, (COLORREF)pField->hImage);
- pFields[nIdx].rect = lpdis->rcItem;
+ pField->rect = lpdis->rcItem;
// Calculate needed size of the control
- DrawText(lpdis->hDC, pFields[nIdx].pszText, -1, &pFields[nIdx].rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_CALCRECT);
- pFields[nIdx].rect.right += 4;
- pFields[nIdx].rect.bottom = lpdis->rcItem.bottom;
+ DrawText(lpdis->hDC, pField->pszText, -1, &pField->rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_CALCRECT);
+ pField->rect.right += 4;
+ pField->rect.bottom = lpdis->rcItem.bottom;
// Resize but don't move
- SetWindowPos(lpdis->hwndItem, NULL, 0, 0, pFields[nIdx].rect.right - pFields[nIdx].rect.left,
- pFields[nIdx].rect.bottom - pFields[nIdx].rect.top, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
+ SetWindowPos(lpdis->hwndItem, NULL, 0, 0, pField->rect.right - pField->rect.left,
+ pField->rect.bottom - pField->rect.top, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
// Draw the text
- lpdis->rcItem = pFields[nIdx].rect;
+ lpdis->rcItem = pField->rect;
// Add little margin to avoid focus rect over text
lpdis->rcItem.right += 2; lpdis->rcItem.left += 2;
- DrawText(lpdis->hDC, pFields[nIdx].pszText, -1, &lpdis->rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE );
+ DrawText(lpdis->hDC, pField->pszText, -1, &lpdis->rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE );
#ifdef IO_LINK_UNDERLINED
DeleteObject(SelectObject(lpdis->hDC, OldFont));
#endif
@@ -809,6 +776,7 @@ int WINAPI StaticLINKWindowProc(HWND hWin, UINT uMsg, LPARAM wParam, WPARAM lPar
int StaticField = FindControlIdx(GetDlgCtrlID(hWin));
if (StaticField < 0)
return 0;
+ FieldType *pField = pFields + StaticField;
switch(uMsg)
{
@@ -817,9 +785,9 @@ int WINAPI StaticLINKWindowProc(HWND hWin, UINT uMsg, LPARAM wParam, WPARAM lPar
case WM_KEYDOWN:
{
if ( wParam == VK_RETURN )
- WMCommandProc(hMainWindow, pFields[StaticField].nControlID, pFields[StaticField].hwnd, BN_CLICKED);
+ WMCommandProc(hMainWindow, pField->nControlID, pField->hwnd, BN_CLICKED);
else if ( wParam == VK_TAB )
- SendMessage(hMainWindow, WM_NEXTDLGCTL, GetKeyState(VK_SHIFT) & 0x8000, FALSE);
+ mySendMessage(hMainWindow, WM_NEXTDLGCTL, GetKeyState(VK_SHIFT) & 0x8000, FALSE);
}
break;
case WM_SETCURSOR:
@@ -835,7 +803,7 @@ int WINAPI StaticLINKWindowProc(HWND hWin, UINT uMsg, LPARAM wParam, WPARAM lPar
}
}
}
- return CallWindowProc((WNDPROC)pFields[StaticField].nParentIdx, hWin, uMsg, wParam, lParam);
+ return CallWindowProc((WNDPROC)pField->nParentIdx, hWin, uMsg, wParam, lParam);
}
#endif
@@ -843,12 +811,11 @@ int old_cancel_visible;
int WINAPI createCfgDlg()
{
- UINT nAddMsg, nFindMsg, nSetSelMsg;
-
g_is_back=0;
g_is_cancel=0;
- if (!hMainWindow)
+ HWND mainwnd = hMainWindow;
+ if (!mainwnd)
{
popstring(NULL);
pushstring("error finding mainwnd");
@@ -862,7 +829,7 @@ int WINAPI createCfgDlg()
return 1;
}
- HWND childwnd=GetDlgItem(hMainWindow,nRectId);
+ HWND childwnd=GetDlgItem(mainwnd,nRectId);
if (!childwnd)
{
popstring(NULL);
@@ -870,9 +837,9 @@ int WINAPI createCfgDlg()
return 1;
}
- hCancelButton = GetDlgItem(hMainWindow,IDCANCEL);
- hInitialFocus = hNextButton = GetDlgItem(hMainWindow,IDOK);
- hBackButton = GetDlgItem(hMainWindow,3);
+ hCancelButton = GetDlgItem(mainwnd,IDCANCEL);
+ hInitialFocus = hNextButton = GetDlgItem(mainwnd,IDOK);
+ hBackButton = GetDlgItem(mainwnd,3);
if (pszCancelButtonText) SetWindowText(hCancelButton,pszCancelButtonText);
if (pszNextButtonText) SetWindowText(hNextButton,pszNextButtonText);
@@ -882,16 +849,16 @@ int WINAPI createCfgDlg()
if (bCancelEnabled!=-1) EnableWindow(hCancelButton,bCancelEnabled);
if (bCancelShow!=-1) old_cancel_visible=ShowWindow(hCancelButton,bCancelShow?SW_SHOWNA:SW_HIDE);
- HFONT hFont = (HFONT)SendMessage(hMainWindow, WM_GETFONT, 0, 0);
+ HFONT hFont = (HFONT)mySendMessage(mainwnd, WM_GETFONT, 0, 0);
RECT dialog_r;
int width;
- hConfigWindow=CreateDialog(m_hInstance,MAKEINTRESOURCE(IDD_DIALOG1),hMainWindow,cfgDlgProc);
+ hConfigWindow=CreateDialog(m_hInstance,MAKEINTRESOURCE(IDD_DIALOG1),mainwnd,cfgDlgProc);
if (hConfigWindow)
{
GetWindowRect(childwnd,&dialog_r);
- ScreenToClient(hMainWindow,(LPPOINT)&dialog_r);
- ScreenToClient(hMainWindow,((LPPOINT)&dialog_r)+1);
+ ScreenToClient(mainwnd,(LPPOINT)&dialog_r);
+ ScreenToClient(mainwnd,((LPPOINT)&dialog_r)+1);
width = dialog_r.right-dialog_r.left;
SetWindowPos(
hConfigWindow,
@@ -903,7 +870,7 @@ int WINAPI createCfgDlg()
SWP_NOZORDER|SWP_NOACTIVATE
);
// Sets the font of IO window to be the same as the main window
- SendMessage(hConfigWindow, WM_SETFONT, (WPARAM)hFont, TRUE);
+ mySendMessage(hConfigWindow, WM_SETFONT, (WPARAM)hFont, TRUE);
}
else
{
@@ -1002,41 +969,46 @@ int WINAPI createCfgDlg()
DEFAULT_STYLES | WS_TABSTOP | BS_OWNERDRAW | BS_RIGHT,
0,
0 },
+ { "BUTTON", // FIELD_BUTTON
+ DEFAULT_STYLES | WS_TABSTOP,
+ DEFAULT_STYLES | WS_TABSTOP | BS_RIGHT,
+ 0,
+ 0 }
};
- int nType = pFields[nIdx].nType;
+ FieldType *pField = pFields + nIdx;
#undef DEFAULT_STYLES
- if (nType < 1 || nType > (sizeof(ClassTable) / sizeof(ClassTable[0])))
+ if (pField->nType < 1 || pField->nType > (sizeof(ClassTable) / sizeof(ClassTable[0])))
continue;
DWORD dwStyle, dwExStyle;
if (bRTL) {
- dwStyle = ClassTable[pFields[nIdx].nType - 1].dwRTLStyle;
- dwExStyle = ClassTable[pFields[nIdx].nType - 1].dwRTLExStyle;
+ dwStyle = ClassTable[pField->nType - 1].dwRTLStyle;
+ dwExStyle = ClassTable[pField->nType - 1].dwRTLExStyle;
}
else {
- dwStyle = ClassTable[pFields[nIdx].nType - 1].dwStyle;
- dwExStyle = ClassTable[pFields[nIdx].nType - 1].dwExStyle;
+ dwStyle = ClassTable[pField->nType - 1].dwStyle;
+ dwExStyle = ClassTable[pField->nType - 1].dwExStyle;
}
// Convert from dialog units
RECT rect;
- rect.left = MulDiv(pFields[nIdx].rect.left, baseUnitX, 4);
- rect.right = MulDiv(pFields[nIdx].rect.right, baseUnitX, 4);
- rect.top = MulDiv(pFields[nIdx].rect.top, baseUnitY, 8);
- rect.bottom = MulDiv(pFields[nIdx].rect.bottom, baseUnitY, 8);
+ rect.left = MulDiv(pField->rect.left, baseUnitX, 4);
+ rect.right = MulDiv(pField->rect.right, baseUnitX, 4);
+ rect.top = MulDiv(pField->rect.top, baseUnitY, 8);
+ rect.bottom = MulDiv(pField->rect.bottom, baseUnitY, 8);
- if (pFields[nIdx].rect.left < 0)
+ if (pField->rect.left < 0)
rect.left += dialog_r.right - dialog_r.left;
- if (pFields[nIdx].rect.right < 0)
+ if (pField->rect.right < 0)
rect.right += dialog_r.right - dialog_r.left;
- if (pFields[nIdx].rect.top < 0)
+ if (pField->rect.top < 0)
rect.top += dialog_r.bottom - dialog_r.top;
- if (pFields[nIdx].rect.bottom < 0)
+ if (pField->rect.bottom < 0)
rect.bottom += dialog_r.bottom - dialog_r.top;
if (bRTL) {
@@ -1045,61 +1017,63 @@ int WINAPI createCfgDlg()
rect.left = width - right;
}
- char *title = pFields[nIdx].pszText;
- switch (nType) {
+ char *title = pField->pszText;
+ switch (pField->nType) {
case FIELD_ICON:
case FIELD_BITMAP:
title = NULL; // otherwise it is treated as the name of a resource
break;
case FIELD_CHECKBOX:
case FIELD_RADIOBUTTON:
- if (pFields[nIdx].nFlags & FLAG_RIGHT)
+ case FIELD_BUTTON:
+ if (pField->nFlags & FLAG_RIGHT)
dwStyle |= BS_RIGHTBUTTON;
break;
+ case FIELD_TEXT:
case FIELD_FILEREQUEST:
case FIELD_DIRREQUEST:
- case FIELD_TEXT:
- if (pFields[nIdx].nFlags & FLAG_PASSWORD)
+ if (pField->nFlags & FLAG_PASSWORD)
dwStyle |= ES_PASSWORD;
- if (pFields[nIdx].nFlags & FLAG_ONLYNUMBERS)
+ if (pField->nFlags & FLAG_ONLYNUMBERS)
dwStyle |= ES_NUMBER;
- if (pFields[nIdx].nFlags & FLAG_MULTILINE)
+ if (pField->nFlags & FLAG_MULTILINE)
{
dwStyle |= ES_MULTILINE | ES_AUTOVSCROLL;
// Enable word-wrap unless we have a horizontal scroll bar
- if (!(pFields[nIdx].nFlags & FLAG_HSCROLL))
+ // or it has been explicitly disallowed
+ if (!(pField->nFlags & (FLAG_HSCROLL | FLAG_NOWORDWRAP)))
dwStyle &= ~ES_AUTOHSCROLL;
- ConvertNewLines(pFields[nIdx].pszState);
+ ConvertNewLines(pField->pszState);
}
- if (pFields[nIdx].nFlags & FLAG_WANTRETURN)
+ if (pField->nFlags & FLAG_WANTRETURN)
dwStyle |= ES_WANTRETURN;
- if (pFields[nIdx].nFlags & FLAG_VSCROLL)
+ if (pField->nFlags & FLAG_VSCROLL)
dwStyle |= WS_VSCROLL;
- if (pFields[nIdx].nFlags & FLAG_HSCROLL)
+ if (pField->nFlags & FLAG_HSCROLL)
dwStyle |= WS_HSCROLL;
- if (pFields[nIdx].nFlags & FLAG_READONLY)
+ if (pField->nFlags & FLAG_READONLY)
dwStyle |= ES_READONLY;
- title = pFields[nIdx].pszState;
+ title = pField->pszState;
break;
case FIELD_COMBOBOX:
- dwStyle |= (pFields[nIdx].nFlags & FLAG_DROPLIST) ? CBS_DROPDOWNLIST : CBS_DROPDOWN;
- title = pFields[nIdx].pszState;
+ dwStyle |= (pField->nFlags & FLAG_DROPLIST) ? CBS_DROPDOWNLIST : CBS_DROPDOWN;
+ title = pField->pszState;
break;
case FIELD_LISTBOX:
- if (pFields[nIdx].nFlags & FLAG_EXTENDEDSEL)
+ if (pField->nFlags & FLAG_EXTENDEDSEL)
dwStyle |= LBS_EXTENDEDSEL;
- if (pFields[nIdx].nFlags & FLAG_MULTISELECT)
+ if (pField->nFlags & FLAG_MULTISELECT)
dwStyle |= LBS_MULTIPLESEL;
break;
}
- if (pFields[nIdx].nFlags & FLAG_DISABLED) dwStyle |= WS_DISABLED;
- if (pFields[nIdx].nFlags & FLAG_GROUP) dwStyle |= WS_GROUP;
- if (pFields[nIdx].nFlags & FLAG_NOTABSTOP) dwStyle &= ~WS_TABSTOP;
+ if (pField->nFlags & FLAG_DISABLED) dwStyle |= WS_DISABLED;
+ if (pField->nFlags & FLAG_GROUP) dwStyle |= WS_GROUP;
+ if (pField->nFlags & FLAG_NOTABSTOP) dwStyle &= ~WS_TABSTOP;
- HWND hwCtrl = pFields[nIdx].hwnd = CreateWindowEx(
+ HWND hwCtrl = pField->hwnd = CreateWindowEx(
dwExStyle,
- ClassTable[pFields[nIdx].nType - 1].pszClass,
+ ClassTable[pField->nType - 1].pszClass,
title,
dwStyle,
rect.left,
@@ -1107,126 +1081,142 @@ int WINAPI createCfgDlg()
rect.right - rect.left,
rect.bottom - rect.top,
hConfigWindow,
- (HMENU)pFields[nIdx].nControlID,
+ (HMENU)pField->nControlID,
m_hInstance,
NULL
);
if (hwCtrl) {
// Sets the font of IO window to be the same as the main window
- SendMessage(hwCtrl, WM_SETFONT, (WPARAM)hFont, TRUE);
+ mySendMessage(hwCtrl, WM_SETFONT, (WPARAM)hFont, TRUE);
// Set initial focus to the first appropriate field
if ((hInitialFocus == hNextButton) && (dwStyle & WS_TABSTOP))
hInitialFocus = hwCtrl;
// make sure we created the window, then set additional attributes
- //if (pFields[nIdx].nMaxLength > 0) {
- switch (nType) {
- case FIELD_TEXT:
- SendMessage(hwCtrl, WM_SETTEXT, 0, (LPARAM)title);
- case FIELD_DIRREQUEST:
- case FIELD_FILEREQUEST:
- SendMessage(hwCtrl, EM_LIMITTEXT, (WPARAM)pFields[nIdx].nMaxLength, (LPARAM)0);
- break;
- }
- //}
- if ((nType == FIELD_CHECKBOX) || (nType == FIELD_RADIOBUTTON)) {
- if (pFields[nIdx].pszState[0] == '1')
- {
- SendMessage(hwCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
- }
- } else if (pFields[nIdx].pszListItems && (
- ((nType == FIELD_COMBOBOX) && (nAddMsg = CB_ADDSTRING)
- && (nFindMsg = CB_FINDSTRINGEXACT) && (nSetSelMsg = CB_SETCURSEL)) ||
- ((nType == FIELD_LISTBOX ) && (nAddMsg = LB_ADDSTRING)
- && (nFindMsg = LB_FINDSTRINGEXACT) && (nSetSelMsg = LB_SETCURSEL))
- )) {
- // if this is a listbox or combobox, we need to add the list items.
- char *pszStart, *pszEnd, *pszList;
- pszStart = pszEnd = pszList = STRDUP(pFields[nIdx].pszListItems);
- while ((*pszEnd) && (*pszStart)) {
- if (*pszEnd == '|') {
- *pszEnd = '\0';
- if (pszEnd > pszStart) {
- SendMessage(hwCtrl, nAddMsg, 0, (LPARAM)pszStart);
+ switch (pField->nType) {
+ case FIELD_TEXT:
+ mySendMessage(hwCtrl, WM_SETTEXT, 0, (LPARAM)title);
+ // no break;
+ case FIELD_FILEREQUEST:
+ case FIELD_DIRREQUEST:
+ mySendMessage(hwCtrl, EM_LIMITTEXT, (WPARAM)pField->nMaxLength, (LPARAM)0);
+ break;
+
+ case FIELD_CHECKBOX:
+ case FIELD_RADIOBUTTON:
+ if (pField->pszState[0] == '1')
+ mySendMessage(hwCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
+ break;
+
+ case FIELD_COMBOBOX:
+ case FIELD_LISTBOX:
+ // if this is a listbox or combobox, we need to add the list items.
+ if (pField->pszListItems) {
+ UINT nAddMsg, nFindMsg, nSetSelMsg;
+ if (pField->nType == FIELD_COMBOBOX) {
+ nAddMsg = CB_ADDSTRING;
+ nFindMsg = CB_FINDSTRINGEXACT;
+ nSetSelMsg = CB_SETCURSEL;
}
- // jump to the next item, skip any redundant | characters
- do { pszEnd++; } while (*pszEnd == '|');
- pszStart = pszEnd;
- }
- pszEnd++;
- }
- FREE(pszList);
- if (pFields[nIdx].pszState) {
- if (pFields[nIdx].nFlags & (FLAG_MULTISELECT|FLAG_EXTENDEDSEL) && nFindMsg == LB_FINDSTRINGEXACT) {
- SendMessage(hwCtrl, LB_SETSEL, FALSE, -1);
- pszStart = pszEnd = pFields[nIdx].pszState;
- while (*pszStart) {
- char cLast = *pszEnd;
- if (*pszEnd == '|') *pszEnd = '\0';
- if (!*pszEnd) {
+ else {
+ nAddMsg = LB_ADDSTRING;
+ nFindMsg = LB_FINDSTRINGEXACT;
+ nSetSelMsg = LB_SETCURSEL;
+ }
+ char *pszStart, *pszEnd, *pszList;
+ pszStart = pszEnd = pszList = STRDUP(pField->pszListItems);
+ while ((*pszEnd) && (*pszStart)) {
+ if (*pszEnd == '|') {
+ *pszEnd = '\0';
if (pszEnd > pszStart) {
- int nItem = SendMessage(hwCtrl, nFindMsg, -1, (LPARAM)pszStart);
- if (nItem != CB_ERR) { // CB_ERR == LB_ERR == -1
- SendMessage(hwCtrl, LB_SETSEL, TRUE, nItem);
- }
- }
- if (cLast) {
- do {
- pszEnd++;
- } while (*pszEnd == '|');
+ mySendMessage(hwCtrl, nAddMsg, 0, (LPARAM)pszStart);
}
+ // jump to the next item, skip any redundant | characters
+ do { pszEnd++; } while (*pszEnd == '|');
pszStart = pszEnd;
}
pszEnd++;
}
- }
- else {
- int nItem = SendMessage(hwCtrl, nFindMsg, -1, (LPARAM)pFields[nIdx].pszState);
- if (nItem != CB_ERR) { // CB_ERR == LB_ERR == -1
- SendMessage(hwCtrl, nSetSelMsg, nItem, 0);
+ FREE(pszList);
+ if (pField->pszState) {
+ if (pField->nFlags & (FLAG_MULTISELECT|FLAG_EXTENDEDSEL) && nFindMsg == LB_FINDSTRINGEXACT) {
+ mySendMessage(hwCtrl, LB_SETSEL, FALSE, -1);
+ pszStart = pszEnd = pField->pszState;
+ while (*pszStart) {
+ char cLast = *pszEnd;
+ if (*pszEnd == '|') *pszEnd = '\0';
+ if (!*pszEnd) {
+ if (pszEnd > pszStart) {
+ int nItem = mySendMessage(hwCtrl, nFindMsg, -1, (LPARAM)pszStart);
+ if (nItem != CB_ERR) { // CB_ERR == LB_ERR == -1
+ mySendMessage(hwCtrl, LB_SETSEL, TRUE, nItem);
+ }
+ }
+ if (cLast) {
+ do {
+ pszEnd++;
+ } while (*pszEnd == '|');
+ }
+ pszStart = pszEnd;
+ }
+ pszEnd++;
+ }
+ }
+ else {
+ int nItem = mySendMessage(hwCtrl, nFindMsg, -1, (LPARAM)pField->pszState);
+ if (nItem != CB_ERR) { // CB_ERR == LB_ERR == -1
+ mySendMessage(hwCtrl, nSetSelMsg, nItem, 0);
+ }
+ }
}
}
- }
- } else if (nType == FIELD_BITMAP || nType == FIELD_ICON) {
- WPARAM nImageType = nType == FIELD_BITMAP ? IMAGE_BITMAP : IMAGE_ICON;
- LPARAM nImage = 0;
- if (pFields[nIdx].pszText) {
- pFields[nIdx].hImage = LoadImage(
- m_hInstance,
- pFields[nIdx].pszText,
+ break;
+
+ case FIELD_ICON:
+ case FIELD_BITMAP:
+ {
+ WPARAM nImageType = pField->nType == FIELD_BITMAP ? IMAGE_BITMAP : IMAGE_ICON;
+ LPARAM nImage = 0;
+ if (pField->pszText) {
+ pField->hImage = LoadImage(
+ m_hInstance,
+ pField->pszText,
+ nImageType,
+ (pField->nFlags & FLAG_RESIZETOFIT)
+ ? (rect.right - rect.left)
+ : 0,
+ (pField->nFlags & FLAG_RESIZETOFIT)
+ ? (rect.bottom - rect.top)
+ : 0,
+ LR_LOADFROMFILE
+ );
+ nImage = (LPARAM)pField->hImage;
+ }
+ else
+ nImage = (LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(103));
+ mySendMessage(
+ hwCtrl,
+ STM_SETIMAGE,
nImageType,
- (pFields[nIdx].nFlags & FLAG_RESIZETOFIT)
- ? (rect.right - rect.left)
- : 0,
- (pFields[nIdx].nFlags & FLAG_RESIZETOFIT)
- ? (rect.bottom - rect.top)
- : 0,
- LR_LOADFROMFILE
+ nImage
);
- nImage = (LPARAM)pFields[nIdx].hImage;
+ break;
}
- else
- nImage = (LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(103));
- SendMessage(
- hwCtrl,
- STM_SETIMAGE,
- nImageType,
- nImage
- );
- }
+
#ifdef IO_ENABLE_LINK
- else if (nType == FIELD_LINK) {
- pFields[nIdx].nParentIdx = SetWindowLong(hwCtrl, GWL_WNDPROC, (long)StaticLINKWindowProc);
- }
+ case FIELD_LINK:
+ pField->nParentIdx = SetWindowLong(hwCtrl, GWL_WNDPROC, (long)StaticLINKWindowProc);
+ break;
#endif
+ }
}
}
if (pszTitle)
- SetWindowText(hMainWindow,pszTitle);
+ SetWindowText(mainwnd,pszTitle);
pFilenameStackEntry = *g_stacktop;
*g_stacktop = (*g_stacktop)->next;
- char tmp[32];
+ static char tmp[32];
wsprintf(tmp,"%d",hConfigWindow);
pushstring(tmp);
return 0;
@@ -1237,11 +1227,11 @@ void WINAPI showCfgDlg()
lpWndProcOld = (void *) SetWindowLong(hMainWindow,DWL_DLGPROC,(long)ParentWndProc);
// Tell NSIS to remove old inner dialog and pass handle of the new inner dialog
- SendMessage(hMainWindow, WM_NOTIFY_CUSTOM_READY, (WPARAM)hConfigWindow, 0);
+ mySendMessage(hMainWindow, WM_NOTIFY_CUSTOM_READY, (WPARAM)hConfigWindow, 0);
ShowWindow(hConfigWindow, SW_SHOWNA);
SetFocus(hInitialFocus);
- g_done=0;
+ g_done = g_NotifyField = 0;
while (!g_done) {
MSG msg;
@@ -1269,16 +1259,17 @@ void WINAPI showCfgDlg()
int i = nNumFields;
while (i--) {
- FREE(pFields[i].pszText);
- FREE(pFields[i].pszState);
- FREE(pFields[i].pszListItems);
- FREE(pFields[i].pszFilter);
- FREE(pFields[i].pszRoot);
- if (pFields[i].nType == FIELD_BITMAP) {
- DeleteObject(pFields[i].hImage);
+ FieldType *pField = pFields + i;
+ FREE(pField->pszText);
+ FREE(pField->pszState);
+ FREE(pField->pszListItems);
+ FREE(pField->pszFilter);
+ FREE(pField->pszRoot);
+ if (pField->nType == FIELD_BITMAP) {
+ DeleteObject(pField->hImage);
}
- if (pFields[i].nType == FIELD_ICON) {
- DestroyIcon((HICON)pFields[i].hImage);
+ if (pField->nType == FIELD_ICON) {
+ DestroyIcon((HICON)pField->hImage);
}
}
FREE(pFields);
diff --git a/Contrib/InstallOptions/Readme.html b/Contrib/InstallOptions/Readme.html
index 070db650..e5149861 100644
--- a/Contrib/InstallOptions/Readme.html
+++ b/Contrib/InstallOptions/Readme.html
@@ -54,14 +54,14 @@ h1
text-align: center;
margin: 20px;
}
-
+
h2
{
font-size: 165%;
color: #7A7272;
font-weight: normal;
}
-
+
h3
{
font-size: 150%;
@@ -85,13 +85,13 @@ a:link, a:visited, a:active
color: #294F75;
text-decoration: none;
}
-
+
a:hover
{
color: #182634;
text-decoration: underline;
}
-
+
.subtable
{
border: 0px;
@@ -199,6 +199,14 @@ according to a different rect than NSIS's dialogs rect.
If 1 is specified the dialog will be mirrored and all texts will be aligned
to the right. Use NSIS's $(^RTL) to fill this field, it's the easiest way. |
+
+State |
+(output) |
+This is not something you have to supply yourself but is set by
+InstallOptions, before calling your custom page validation function, to the field
+number of the custom Button control (or other control having the Notify flag) the
+user pressed, if any.
+ |
Each field section has the heading "Field #" where # must be sequential numbers from 1 to
NumFields. Each Field section can contain the following values:
@@ -209,14 +217,14 @@ NumFields. Each Field section can contain the following values:
Type of control to be created. Valid values are "Label",
"Text", "Password", "Combobox", "DropList", "Listbox",
"CheckBox", "RadioButton", "FileRequest", "DirRequest"
-"Icon", "Bitmap" or "GroupBox".
+"Icon", "Bitmap", "GroupBox", "Link" or "Button".
A "Label" is used to display static text. (i.e. a caption for a textbox)
A "Text" and "Password" accept text input from the user. "Password"
masks the input with * characters.
A "Combobox" allows the user to type text not in the popup list, a "Droplist"
only allows selection of items in the list.
-A "listbox" shows multiple items and can optionally allow the user to select more than one
+A "Listbox" shows multiple items and can optionally allow the user to select more than one
item.
A "CheckBox" control displays a check box with label.
A "RadioButton" control displays a radio button with label.
@@ -228,7 +236,9 @@ An "Icon" control displays an icon. Use no Text to use the installer ic
A "Bitmap" control displays a bitmap.
A "GroupBox" control displays a frame to group controls.
A "Link" control displays a static hot text, when the user click the control the contents
-of State (e.g. http://...) will be executed using ShellExecute
|
+of State (e.g. http://...) will be executed using ShellExecute
+A "Button" control displays a push button that your NSIS script can act on
+when pressed. See the "NOTIFY" flag for more information.
Text |
@@ -271,7 +281,7 @@ You should not use this on a "combobox" since the user can not control
selected.
This should be set to a maximum of 260 for "FileRequest" and "DirRequest"
controls.
-Ignored on "label" controls.
+Ignored on "Label" controls.
MinLen |
@@ -444,9 +454,16 @@ carriage return be inserted when the user presses the ENTER key while entering t
box.
+NOWORDWRAP |
+Used by "Text" controls with multiple-line. Disables the
+word-wrap that occurs when long lines are entered. Long lines instead scroll off to the
+side. Specifying the HSCROLL flag also has this effect.
+ |
+
+
HSCROLL |
Used by "Text" controls with multiple-line. Show a horizontal
-scrollbar. |
+scrollbar and disable word-wrap.
VSCROLL |
@@ -458,6 +475,16 @@ scrollbar.
Used by "Text" controls. Prevents the user from entering or editing
text in the edit control, but allow the user to select and copy the text. |
+
+NOTIFY |
+Used by "Button", "CheckBox" and "RadioButton"
+controls. Causes InstallOptions to call your NSIS custom page validation/leave function
+whenever the button is pressed. Your validation/leave function can read the "State"
+value from the "Settings" section to determine which custom button has been
+pressed, if any, and perform some appropriate action followed by an Abort instruction
+(to tell NSIS to return to the page). The Contrib\InstallOptions folder contains an
+example script showing how this might be used. |
+
@@ -691,6 +718,16 @@ FunctionEnd
Version history
+- DLL version 2.3 (12/4/2003)
+
+- Added new control type "Button"
+- Added new flag "NOTIFY"
+- Added new flag "NOWORDWRAP" for multi-line text boxes
+- Reduced size down to 12K
+
+
+
+
- DLL version 2.2 (4/9/2003)
- Added new control "link"
diff --git a/Contrib/InstallOptions/testnotify.ini b/Contrib/InstallOptions/testnotify.ini
new file mode 100644
index 00000000..f741b568
--- /dev/null
+++ b/Contrib/InstallOptions/testnotify.ini
@@ -0,0 +1,83 @@
+[Settings]
+NumFields=9
+
+[Field 1]
+Type=Groupbox
+Text="This is a group box..."
+Left=0
+Right=-1
+Top=0
+Bottom=-4
+
+[Field 2]
+Type=Checkbox
+Text=Install support for X
+Flags=NOTIFY
+State=1
+Left=10
+Right=100
+Top=17
+Bottom=25
+
+[Field 3]
+Type=Checkbox
+Text=Install support for Y
+State=0
+Left=10
+Right=100
+Top=30
+Bottom=38
+
+[Field 4]
+Type=Checkbox
+Text=Install support for Z
+State=0
+Left=10
+Right=100
+Top=43
+Bottom=51
+
+[Field 5]
+Type=FileRequest
+Flags=GROUP|FILE_MUST_EXIST|FILE_EXPLORER|FILE_HIDEREADONLY
+State=C:\poop.poop
+Filter=Poop Files|*.poop|All files|*.*
+Left=10
+Right=-10
+Top=56
+Bottom=69
+
+[Field 6]
+Type=DirRequest
+Text=Select a directory...
+State=C:\Program Files\NSIS
+Left=10
+Right=-10
+Top=74
+Bottom=87
+
+[Field 7]
+Type=Label
+Text=This is a label...
+Left=10
+Right=-10
+Top=89
+Bottom=97
+
+[Field 8]
+Type=Text
+Flags=MULTILINE|VSCROLL|WANTRETURN|NOWORDWRAP
+State="Multiline\r\nedit..."
+Left=10
+Right=-10
+Top=97
+Bottom=118
+
+[Field 9]
+Type=Button
+Flags=NOTIFY
+Text=Clear
+Left=-60
+Right=-10
+Top=27
+Bottom=41
diff --git a/Contrib/InstallOptions/testnotify.nsi b/Contrib/InstallOptions/testnotify.nsi
new file mode 100644
index 00000000..40cd06ba
--- /dev/null
+++ b/Contrib/InstallOptions/testnotify.nsi
@@ -0,0 +1,105 @@
+; InstallOptions script demonstrating custom buttons
+;----------------------------------------------------
+
+!include WinMessages.nsh
+
+Var hwnd ; Window handle of the custom page
+
+; The name of the installer
+Name "InstallOptions Test"
+
+; The file to write
+OutFile "TestNotify.exe"
+
+; Show install details
+ShowInstDetails show
+
+; Called before anything else as installer initialises
+Function .onInit
+
+ ; Extract InstallOptions files
+ ; $PLUGINSDIR will automatically be removed when the installer closes
+ InitPluginsDir
+ File /oname=$PLUGINSDIR\test.ini "testnotify.ini"
+
+FunctionEnd
+
+; Our custom page
+Page custom ShowCustom LeaveCustom ": Testing InstallOptions"
+
+Function ShowCustom
+
+ ; Initialise the dialog but don't show it yet
+ InstallOptions::initDialog /NOUNLOAD "$PLUGINSDIR\test.ini"
+ ; In this mode InstallOptions returns the window handle so we can use it
+ Pop $hwnd
+ ; Now show the dialog and wait for it to finish
+ InstallOptions::show
+ ; Finally fetch the InstallOptions status value (we don't care what it is though)
+ Pop $0
+
+FunctionEnd
+
+Function LeaveCustom
+
+ ; At this point the user has either pressed Next or one of our custom buttons
+ ; We find out which by reading from the INI file
+ ReadINIStr $0 "$PLUGINSDIR\test.ini" "Settings" "State"
+ StrCmp $0 0 validate ; Next button?
+ StrCmp $0 2 supportx ; "Install support for X"?
+ StrCmp $0 9 clearbtn ; "Clear" button?
+ Abort ; Return to the page
+
+supportx:
+ ; Make the FileRequest field depend on the first checkbox
+ ReadINIStr $0 "$PLUGINSDIR\test.ini" "Field 2" "State"
+ GetDlgItem $1 $hwnd 1204 ; PathRequest control (1200 + field 5 - 1)
+ EnableWindow $1 $0
+ GetDlgItem $1 $hwnd 1205 ; ... button (the following control)
+ EnableWindow $1 $0
+ Abort ; Return to the page
+
+clearbtn:
+ ; Clear all text fields
+ GetDlgItem $1 $hwnd 1204 ; PathRequest control (1200 + field 5 - 1)
+ SendMessage $1 ${WM_SETTEXT} 0 "STR:"
+ GetDlgItem $1 $hwnd 1206 ; DirRequest control (1200 + field 6 - 1 + 1 browse button)
+ SendMessage $1 ${WM_SETTEXT} 0 "STR:"
+ GetDlgItem $1 $hwnd 1209 ; DirRequest control (1200 + field 8 - 1 + 2 browse buttons)
+ SendMessage $1 ${WM_SETTEXT} 0 "STR:"
+ Abort ; Return to the page
+
+validate:
+ ; At this point we know the Next button was pressed, so perform any validation
+ ReadINIStr $0 "$PLUGINSDIR\test.ini" "Field 2" "State"
+ StrCmp $0 1 done
+ ReadINIStr $0 "$PLUGINSDIR\test.ini" "Field 3" "State"
+ StrCmp $0 1 done
+ ReadINIStr $0 "$PLUGINSDIR\test.ini" "Field 4" "State"
+ StrCmp $0 1 done
+ MessageBox MB_ICONEXCLAMATION|MB_OK "You must select at least one install option!"
+ Abort
+done:
+
+FunctionEnd
+
+; Installation page
+Page instfiles
+
+Section
+
+ ;Get Install Options dialog user input
+ ReadINIStr $0 "$PLUGINSDIR\test.ini" "Field 2" "State"
+ DetailPrint "Install X=$0"
+ ReadINIStr $0 "$PLUGINSDIR\test.ini" "Field 3" "State"
+ DetailPrint "Install Y=$0"
+ ReadINIStr $0 "$PLUGINSDIR\test.ini" "Field 4" "State"
+ DetailPrint "Install Z=$0"
+ ReadINIStr $0 "$PLUGINSDIR\test.ini" "Field 5" "State"
+ DetailPrint "File=$0"
+ ReadINIStr $0 "$PLUGINSDIR\test.ini" "Field 6" "State"
+ DetailPrint "Dir=$0"
+ ReadINIStr $0 "$PLUGINSDIR\test.ini" "Field 8" "State"
+ DetailPrint "Info=$0"
+
+SectionEnd
diff --git a/Examples/makensis.nsi b/Examples/makensis.nsi
index dbf8241b..48796e7e 100644
--- a/Examples/makensis.nsi
+++ b/Examples/makensis.nsi
@@ -79,9 +79,9 @@ Page custom PageReinstall PageLeaveReinstall
;--------------------------------
;Reserve Files
-
+
;These files should be inserted before other files in the data block
-
+
ReserveFile "makensis.ini"
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
@@ -104,7 +104,7 @@ Section "NSIS Core Files (required)" SecCore
File ..\makensisw.exe
File ..\license.txt
File ..\NSIS.chm
-
+
File ..\NSIS.exe
IfFileExists $INSTDIR\nsisconf.nsi "" +2
Rename $INSTDIR\nsisconf.nsi $INSTDIR\nsisconf.nsh
@@ -119,23 +119,23 @@ Section "NSIS Core Files (required)" SecCore
SetOutPath $INSTDIR\Contrib\Makensisw
File ..\contrib\makensisw\*.txt
-
+
SetOutPath $INSTDIR\Menu
File ..\Menu\*.html
SetOutPath $INSTDIR\Menu\images
File ..\Menu\images\*.gif
-
+
Delete $INSTDIR\makensis.htm
Delete $INSTDIR\Docs\*.html
Delete $INSTDIR\Docs\style.css
RMDir $INSTDIR\Docs
-
+
ReadRegStr $R0 HKCR ".nsi" ""
StrCmp $R0 "NSISFile" 0 no_nsioldassoc
DeleteRegKey HKCR "NSISFile"
Goto nsi
no_nsioldassoc:
-
+
StrCmp $R0 "NSIS.Script" 0 no_nsi
nsi:
WriteRegStr HKCR ".nsi" "" "NSIS.Script"
@@ -144,20 +144,20 @@ Section "NSIS Core Files (required)" SecCore
ReadRegStr $R0 HKCR "NSIS.Script\shell\open\command" ""
StrCmp $R0 "" 0 no_nsiopen
WriteRegStr HKCR "NSIS.Script\shell" "" "open"
- WriteRegStr HKCR "NSIS.Script\shell\open\command" "" 'notepad.exe "%1"'
+ WriteRegStr HKCR "NSIS.Script\shell\open\command" "" 'notepad.exe "%1"'
no_nsiopen:
WriteRegStr HKCR "NSIS.Script\shell\compile" "" "Compile NSIS Script"
WriteRegStr HKCR "NSIS.Script\shell\compile\command" "" '"$INSTDIR\makensisw.exe" "%1"'
WriteRegStr HKCR "NSIS.Script\shell\compile-compressor" "" "Compile NSIS Script (Choose Compressor)"
WriteRegStr HKCR "NSIS.Script\shell\compile-compressor\command" "" '"$INSTDIR\makensisw.exe" /ChooseCompressor "%1"'
no_nsi:
-
+
ReadRegStr $R0 HKCR ".nsh" ""
StrCmp $R0 "NSHFile" 0 no_nsholdassoc
DeleteRegKey HKCR "NSHFile"
Goto nsh
no_nsholdassoc:
-
+
StrCmp ".nsh" "NSIS.Header" 0 no_nsh
nsh:
WriteRegStr HKCR ".nsh" "" "NSIS.Header"
@@ -166,7 +166,7 @@ Section "NSIS Core Files (required)" SecCore
ReadRegStr $R0 HKCR "NSIS.Header\shell\open\command" ""
StrCmp $R0 "" 0 no_nshopen
WriteRegStr HKCR "NSIS.Header\shell" "" "open"
- WriteRegStr HKCR "NSIS.Header\shell\open\command" "" 'notepad.exe "%1"'
+ WriteRegStr HKCR "NSIS.Header\shell\open\command" "" 'notepad.exe "%1"'
no_nshopen:
no_nsh:
@@ -228,11 +228,11 @@ Section "Desktop Shortcut" SecShortcuts
CreateShortCut "$SMPROGRAMS\NSIS\NSIS Documentation.lnk" "$INSTDIR\NSIS.chm"
WriteINIStr "$SMPROGRAMS\NSIS\NSIS Site.url" "InternetShortcut" "URL" "http://nsis.sourceforge.net/"
CreateShortCut "$SMPROGRAMS\NSIS\Uninstall NSIS.lnk" "$INSTDIR\uninst-nsis.exe"
-
+
!endif
CreateShortCut "$DESKTOP\Nullsoft Install System.lnk" "$INSTDIR\NSIS.exe"
-
+
SectionEnd
SubSection "User Interfaces" SecInterfaces
@@ -280,7 +280,7 @@ Section "Modern User Interface" SecInterfacesModernUI
SetOutPath $INSTDIR\Include
File "..\Include\MUI.nsh"
-
+
SectionEnd
Section "Default User Interface" SecInterfacesDefaultUI
@@ -362,10 +362,10 @@ Section "NSIS Update" SecToolsUpdate
SetOutPath $INSTDIR\Bin
File ..\Bin\NSISUpdate.exe
File ..\Bin\InstallCVSData.exe
-
+
IfFileExists "$INSTDIR\CVS\Root" 0 +2
Exec '"$INSTDIR\Bin\InstallCVSData.exe"'
-
+
SectionEnd
Section "Zip2Exe" SecToolsZ2E
@@ -478,7 +478,7 @@ SectionEnd
Section "InstallOptions" SecPluginsIO
SetDetailsPrint textonly
- DetailPrint "Installing Plug-inss | InstallOptions..."
+ DetailPrint "Installing Plug-ins | InstallOptions..."
SetDetailsPrint listonly
SectionIn 1 2
@@ -492,6 +492,8 @@ Section "InstallOptions" SecPluginsIO
File ..\contrib\installoptions\test.nsi
File ..\contrib\installoptions\testlink.ini
File ..\contrib\installoptions\testlink.nsi
+ File ..\contrib\installoptions\testnotify.ini
+ File ..\contrib\installoptions\testnotify.nsi
SectionEnd
Section "Math" SecPluginsMath
@@ -983,17 +985,17 @@ Section -post
; * Always install default icons / bitmaps
!insertmacro SectionFlagIsSet ${SecInterfacesModernUI} ${SF_SELECTED} mui nomui
-
- mui:
+
+ mui:
SetDetailsPrint textonly
DetailPrint "Configurating Modern UI..."
SetDetailsPrint listonly
!insertmacro SectionFlagIsSet ${SecLangFiles} ${SF_SELECTED} langfiles nolangfiles
-
+
nolangfiles:
-
+
SetOutPath "$INSTDIR\Contrib\Language files"
File "..\Contrib\Language files\English.nlf"
SetOutPath "$INSTDIR\Contrib\Modern UI\Language files"
@@ -1003,9 +1005,9 @@ Section -post
langfiles:
!insertmacro SectionFlagIsSet ${SecGraphics} ${SF_SELECTED} graphics nographics
-
+
nographics:
-
+
SetOutPath $INSTDIR\Contrib\Graphics
SetOutPath $INSTDIR\Contrib\Graphics\Checks
File "..\Contrib\Graphics\Checks\modern.bmp"
@@ -1176,7 +1178,7 @@ Section -post
SetDetailsPrint none
RMDir $INSTDIR\Contrib\Source
SetDetailsPrint lastused
-
+
WriteUninstaller $INSTDIR\uninst-nsis.exe
SetDetailsPrint both
@@ -1250,10 +1252,10 @@ FunctionEnd
Function PageReinstall
ReadRegStr $R0 HKLM "Software\NSIS" ""
-
+
StrCmp $R0 "" 0 +2
Abort
-
+
;Detect version
ReadRegDWORD $R0 HKLM "Software\NSIS" "VersionMajor"
IntCmp $R0 ${VER_MAJOR} minor_check new_version older_version
@@ -1296,43 +1298,43 @@ Function PageReinstall
reinst_start:
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "makensis.ini"
-
+
FunctionEnd
Function PageLeaveReinstall
-
+
!insertmacro MUI_INSTALLOPTIONS_READ $R1 "makensis.ini" "Field 2" "State"
StrCmp $R0 "1" 0 +2
StrCmp $R1 "1" reinst_uninstall reinst_done
-
+
StrCmp $R0 "2" 0 +3
StrCmp $R1 "1" reinst_done reinst_uninstall
reinst_uninstall:
ReadRegStr $R1 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NSIS" "UninstallString"
-
+
;Run uninstaller
HideWindow
-
+
ClearErrors
ExecWait '$R1 _?=$INSTDIR'
-
+
IfErrors no_remove_uninstaller
IfFileExists "$INSTDIR\makensis.exe" no_remove_uninstaller
-
+
Delete $R1
RMDir $INSTDIR
-
+
no_remove_uninstaller:
-
+
StrCmp $R0 "2" 0 +2
Quit
-
+
BringToFront
reinst_done:
-
+
FunctionEnd
!macro secSelected SEC
@@ -1415,18 +1417,18 @@ Section Uninstall
SetDetailsPrint textonly
DetailPrint "Deleting Registry Keys..."
SetDetailsPrint listonly
-
+
ReadRegStr $R0 HKCR ".nsi" ""
StrCmp $R0 "NSIS.Script" 0 +2
DeleteRegKey HKCR ".nsi"
-
+
ReadRegStr $R0 HKCR ".nsh" ""
StrCmp $R0 "NSIS.Header" 0 +2
DeleteRegKey HKCR ".nsh"
DeleteRegKey HKCR "NSIS.Script"
DeleteRegKey HKCR "NSIS.Header"
-
+
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NSIS"
DeleteRegKey HKLM "Software\NSIS"
@@ -1444,7 +1446,7 @@ Section Uninstall
Delete $INSTDIR\nsisconf.nsi
Delete $INSTDIR\nsisconf.nsh
Delete $INSTDIR\NSIS.chm
- RMDIR /r $INSTDIR\CVS
+ RMDIR /r $INSTDIR\CVS
RMDir /r $INSTDIR\Contrib
RMDir /r $INSTDIR\Menu
RMDir /r $INSTDIR\Source
@@ -1456,4 +1458,4 @@ Section Uninstall
SetDetailsPrint both
-SectionEnd
\ No newline at end of file
+SectionEnd
diff --git a/Plugins/InstallOptions.dll b/Plugins/InstallOptions.dll
index bf0fd813..7dea3159 100644
Binary files a/Plugins/InstallOptions.dll and b/Plugins/InstallOptions.dll differ