summaryrefslogtreecommitdiff
path: root/Contrib/InstallOptions/InstallerOptions.cpp
diff options
context:
space:
mode:
authorDidier Raboud <odyx@debian.org>2018-03-31 20:38:19 +0200
committerDidier Raboud <odyx@debian.org>2018-03-31 20:38:19 +0200
commitf05798f0619384fdb055f634ca4233378f2779dd (patch)
treeb1f9b212f77580c824cc765ac3778fc6c8f4d4d8 /Contrib/InstallOptions/InstallerOptions.cpp
parent59c41c0897494001ced424157660d4ee59bb5426 (diff)
Import Upstream version 2.32
Diffstat (limited to 'Contrib/InstallOptions/InstallerOptions.cpp')
-rwxr-xr-xContrib/InstallOptions/InstallerOptions.cpp3256
1 files changed, 1628 insertions, 1628 deletions
diff --git a/Contrib/InstallOptions/InstallerOptions.cpp b/Contrib/InstallOptions/InstallerOptions.cpp
index b613b6a..b4f42f7 100755
--- a/Contrib/InstallOptions/InstallerOptions.cpp
+++ b/Contrib/InstallOptions/InstallerOptions.cpp
@@ -1,1628 +1,1628 @@
-/*********************************************************
- *
- * InstallOptions version 2.0 - Plugin for custom pages
- *
- * See Readme.html for documentation and license
- *
- *********************************************************/
-
-#include <windows.h>
-#include <windowsx.h>
-#include <shlobj.h>
-#include <commdlg.h>
-#include <cderr.h>
-#include "resource.h"
-#include "shellapi.h"
-
-#define popstring dontuseme
-#include "../ExDLL/exdll.h"
-#undef popstring
-
-// Use for functions only called from one place to possibly reduce some code
-// size. Allows the source code to remain readable by leaving the function
-// intact.
-#ifdef _MSC_VER
-#define INLINE __forceinline
-#else
-#define INLINE inline
-#endif
-
-void *WINAPI MALLOC(int len) { return (void*)GlobalAlloc(GPTR,len); }
-void WINAPI FREE(void *d) { if (d) GlobalFree((HGLOBAL)d); }
-
-void WINAPI popstring(char *str)
-{
- if (g_stacktop && *g_stacktop)
- {
- stack_t *th = *g_stacktop;
- *g_stacktop = th->next;
- if (str)
- lstrcpy(str, th->text);
- FREE(th);
- }
-}
-
-#define strcpy(x,y) lstrcpy(x,y)
-//#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))
-
-char *WINAPI STRDUP(const char *c)
-{
- char *t=(char*)MALLOC(lstrlen(c)+1);
- return lstrcpy(t,c);
-}
-
-// Turn a pair of chars into a word
-// Turn four chars into a dword
-#ifdef __BIG_ENDIAN__ // Not very likely, but, still...
-#define CHAR2_TO_WORD(a,b) (((WORD)(b))|((a)<<8))
-#define CHAR4_TO_DWORD(a,b,c,d) (((DWORD)CHAR2_TO_WORD(c,d))|(CHAR2_TO_WORD(a,b)<<16))
-#else
-#define CHAR2_TO_WORD(a,b) (((WORD)(a))|((b)<<8))
-#define CHAR4_TO_DWORD(a,b,c,d) (((DWORD)CHAR2_TO_WORD(a,b))|(CHAR2_TO_WORD(c,d)<<16))
-#endif
-
-// Field types
-// NB - the order of this list is important - see below
-
-#define FIELD_INVALID (0)
-#define FIELD_HLINE (1)
-#define FIELD_VLINE (2)
-#define FIELD_LABEL (3)
-#define FIELD_ICON (4)
-#define FIELD_BITMAP (5)
-#define FIELD_BROWSEBUTTON (6)
-#define FIELD_LINK (7)
-#define FIELD_BUTTON (8)
-#define FIELD_GROUPBOX (9)
-#define FIELD_CHECKBOX (10)
-#define FIELD_RADIOBUTTON (11)
-#define FIELD_TEXT (12)
-#define FIELD_FILEREQUEST (13)
-#define FIELD_DIRREQUEST (14)
-#define FIELD_COMBOBOX (15)
-#define FIELD_LISTBOX (16)
-
-#define FIELD_SETFOCUS FIELD_CHECKBOX // First field that qualifies for having the initial keyboard focus
-#define FIELD_CHECKLEN FIELD_TEXT // First field to have length of state value checked against MinLen/MaxLen
-
-//---------------------------------------------------------------------
-// settings
-#define IO_ENABLE_LINK
-
-//#define IO_LINK_UNDERLINED // Uncomment to show links text underlined
-//---------------------------------------------------------------------
-
-// Flags
-
-// LBS_NOTIFY 0x00000001 // LISTBOX/CHECKBOX/RADIOBUTTON/BUTTON/LINK - Notify NSIS script when control is "activated" (exact meaning depends on the type of control)
-// OFN_OVERWRITEPROMPT 0x00000002 // FILEREQUEST
-// OFN_HIDEREADONLY 0x00000004 // FILEREQUEST
-// LBS_MULTIPLESEL 0x00000008 // LISTBOX
-#define FLAG_READONLY 0x00000010 // TEXT/FILEREQUEST/DIRREQUEST
-// BS_LEFTTEXT 0x00000020 // CHECKBOX/RADIOBUTTON
-#define TRANSPARENT_BMP 0x00000020 // BITMAP
-#define FLAG_PASSWORD 0x00000040 // TEXT/FILEREQUEST/DIRREQUEST
-#define FLAG_ONLYNUMBERS 0x00000080 // TEXT/FILEREQUEST/DIRREQUEST
-#define FLAG_MULTILINE 0x00000100 // TEXT/FILEREQUEST/DIRREQUEST
-#define FLAG_NOWORDWRAP 0x00000200 // TEXT/FILEREQUEST/DIRREQUEST - Disable word-wrap in multi-line text boxes
-#define FLAG_WANTRETURN 0x00000400 // TEXT/FILEREQUEST/DIRREQUEST
-// LBS_EXTENDEDSEL 0x00000800 // LISTBOX
-// OFN_PATHMUSTEXIST 0x00000800 // FILEREQUEST
-// OFN_FILEMUSTEXIST 0x00001000 // FILEREQUEST
-// OFN_CREATEPROMPT 0x00002000 // FILEREQUEST
-#define FLAG_DROPLIST 0x00004000 // COMBOBOX
-#define FLAG_RESIZETOFIT 0x00008000 // BITMAP
-// WS_TABSTOP 0x00010000 // *ALL*
-// WS_GROUP 0x00020000 // *ALL*
-#define FLAG_SAVEAS 0x00040000 // FILEREQUEST - Show "Save As" instead of "Open" for FileRequest field
-// OFN_EXPLORER 0x00080000 // FILEREQUEST
-// WS_HSCROLL 0x00100000 // *ALL*
-// WS_VSCROLL 0x00200000 // *ALL*
-// WS_DISABLED 0x08000000 // *ALL*
-#define FLAG_FOCUS 0x10000000 // Controls that can receive focus
-
-struct TableEntry {
- char *pszName;
- int nValue;
-};
-
-int WINAPI LookupToken(TableEntry*, char*);
-int WINAPI LookupTokens(TableEntry*, char*);
-
-void WINAPI ConvertNewLines(char *str);
-
-// all allocated buffers must be first in the struct
-// when adding more allocated buffers to FieldType, don't forget to change this define
-#define FIELD_BUFFERS 6
-struct FieldType {
- char *pszText;
- char *pszState;
- char *pszRoot;
-
- char *pszListItems;
- char *pszFilter;
-
- char *pszValidateText;
- int nMinLength;
- int nMaxLength;
-
- int nType;
- RECT rect;
-
- int nFlags;
-
- HWND hwnd;
- UINT nControlID;
-
- 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
-
- int nField; // field number in INI file
- char *pszHwndEntry; // "HWND" or "HWND2"
-
- long wndProc;
-};
-
-// initial buffer size. buffers will grow as required.
-// use a value larger than MAX_PATH to prevent need for excessive growing.
-#define BUFFER_SIZE 8192 // 8kb of mem is max char count in multiedit
-
-char szBrowseButtonCaption[] = "...";
-
-HWND hConfigWindow = NULL;
-HWND hMainWindow = NULL;
-HWND hCancelButton = NULL;
-HWND hNextButton = NULL;
-HWND hBackButton = NULL;
-
-HINSTANCE m_hInstance = NULL;
-
-struct _stack_t *pFilenameStackEntry = NULL;
-
-char *pszFilename = NULL;
-char *pszTitle = NULL;
-char *pszCancelButtonText = NULL;
-char *pszNextButtonText = NULL;
-char *pszBackButtonText = NULL;
-
-int bBackEnabled = FALSE;
-int bCancelEnabled = FALSE; // by ORTIM: 13-August-2002
-int bCancelShow = FALSE; // by ORTIM: 13-August-2002
-
-int bRTL = FALSE;
-
-FieldType *pFields = NULL;
-#define DEFAULT_RECT 1018
-int nRectId = 0;
-int nNumFields = 0;
-int g_done;
-int g_NotifyField; // Field number of notifying control
-
-int WINAPI FindControlIdx(UINT id)
-{
- for (int nIdx = 0; nIdx < nNumFields; nIdx++)
- if (id == pFields[nIdx].nControlID)
- return nIdx;
- return -1;
-}
-
-LRESULT WINAPI mySendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
-{
- return SendMessage(hWnd, Msg, wParam, lParam);
-}
-
-void WINAPI mySetFocus(HWND hWnd)
-{
- mySendMessage(hMainWindow, WM_NEXTDLGCTL, (WPARAM)hWnd, TRUE);
-}
-
-void WINAPI mySetWindowText(HWND hWnd, LPCTSTR pszText)
-{
- if (pszText)
- SetWindowText(hWnd, pszText);
-}
-
-int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData) {
- static TCHAR szDir[MAX_PATH];
-
- if (uMsg == BFFM_INITIALIZED &&
- GetWindowText(pFields[(int)pData].hwnd, szDir, MAX_PATH) > 0)
- mySendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szDir);
- return 0;
-}
-
-
-bool INLINE ValidateFields() {
- int nIdx;
- int nLength;
-
- // 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 (pField->nType >= FIELD_CHECKLEN) {
- nLength = mySendMessage(pField->hwnd, WM_GETTEXTLENGTH, 0, 0);
-
- if (((pField->nMaxLength > 0) && (nLength > pField->nMaxLength)) ||
- ((pField->nMinLength > 0) && (nLength < pField->nMinLength))) {
- if (pField->pszValidateText) {
- char szTitle[1024];
- GetWindowText(hMainWindow, szTitle, sizeof(szTitle));
- MessageBox(hConfigWindow, pField->pszValidateText, szTitle, MB_OK|MB_ICONWARNING);
- }
- mySetFocus(pField->hwnd);
- return false;
- }
-
- }
- }
- return true;
-}
-
-bool WINAPI SaveSettings(void) {
- static char szField[25];
- int nBufLen = BUFFER_SIZE;
- char *pszBuffer = (char*)MALLOC(nBufLen);
- if (!pszBuffer) return false;
-
- int nIdx;
- int CurrField;
- for (nIdx = 0, CurrField = 1; nIdx < nNumFields; nIdx++, CurrField++) {
- FieldType *pField = pFields + nIdx;
- HWND hwnd = pField->hwnd;
- switch (pField->nType) {
- case FIELD_BROWSEBUTTON:
- if (g_NotifyField > CurrField)
- --g_NotifyField;
- --CurrField;
- default:
- continue;
-
- case FIELD_CHECKBOX:
- case FIELD_RADIOBUTTON:
- wsprintf(pszBuffer, "%d", !!mySendMessage(hwnd, BM_GETCHECK, 0, 0));
- break;
-
- case FIELD_LISTBOX:
- {
- // Ok, this one requires a bit of work.
- // First, we allocate a buffer long enough to hold every item.
- // 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(pField->pszListItems) + 10;
- if (nLength > nBufLen) {
- FREE(pszBuffer);
- nBufLen = nLength;
- pszBuffer = (char*)MALLOC(nBufLen);
- if (!pszBuffer) return false;
- }
- char *pszItem = (char*)MALLOC(nBufLen);
- if (!pszItem) return false;
-
- *pszBuffer = '\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, "|");
- mySendMessage(hwnd, LB_GETTEXT, (WPARAM)nIdx2, (LPARAM)pszItem);
- lstrcat(pszBuffer, pszItem);
- }
- }
-
- FREE(pszItem);
- break;
- }
-
- case FIELD_TEXT:
- case FIELD_FILEREQUEST:
- case FIELD_DIRREQUEST:
- case FIELD_COMBOBOX:
- {
- int nLength = mySendMessage(pField->hwnd, WM_GETTEXTLENGTH, 0, 0);
- if (nLength > nBufLen) {
- FREE(pszBuffer);
- // add a bit extra so we do this less often
- nBufLen = nLength + 20;
- pszBuffer = (char*)MALLOC(nBufLen);
- if (!pszBuffer) return false;
- }
- *pszBuffer='"';
- GetWindowText(hwnd, pszBuffer+1, nBufLen-1);
- pszBuffer[nLength+1]='"';
- pszBuffer[nLength+2]='\0';
-
- 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;
- for (p1 = pszBuffer, p2 = pszBuf2; *p1; p1 = CharNext(p1), p2 = CharNext(p2))
- {
- switch (*p1) {
- case '\t':
- *(LPWORD)p2 = CHAR2_TO_WORD('\\', 't');
- p2++;
- break;
- case '\n':
- *(LPWORD)p2 = CHAR2_TO_WORD('\\', 'n');
- p2++;
- break;
- case '\r':
- *(LPWORD)p2 = CHAR2_TO_WORD('\\', 'r');
- p2++;
- break;
- case '\\':
- *p2++ = '\\';
- default:
- lstrcpyn(p2, p1, CharNext(p1) - p1 + 1);
- break;
- }
- }
- *p2 = 0;
- nBufLen = nBufLen*2;
- FREE(pszBuffer);
- pszBuffer=pszBuf2;
- }
- break;
- }
- }
- wsprintf(szField, "Field %d", CurrField);
- WritePrivateProfileString(szField, "State", pszBuffer, pszFilename);
- }
-
- // Tell NSIS which control was activated, if any
- wsprintf(pszBuffer, "%d", g_NotifyField);
- WritePrivateProfileString("Settings", "State", pszBuffer, pszFilename);
-
- FREE(pszBuffer);
-
- return true;
-}
-
-#define BROWSE_WIDTH 15
-
-static char szResult[BUFFER_SIZE];
-char *pszAppName;
-
-DWORD WINAPI myGetProfileString(LPCTSTR lpKeyName)
-{
- *szResult = '\0';
- return GetPrivateProfileString(pszAppName, lpKeyName, "", szResult, BUFFER_SIZE, pszFilename);
-}
-
-char * WINAPI myGetProfileStringDup(LPCTSTR lpKeyName)
-{
- int nSize = myGetProfileString(lpKeyName);
- if (nSize)
- return strdup(szResult);
- else
- return NULL;
-}
-
-UINT WINAPI myGetProfileInt(LPCTSTR lpKeyName, INT nDefault)
-{
- return GetPrivateProfileInt(pszAppName, lpKeyName, nDefault, pszFilename);
-}
-
-int WINAPI ReadSettings(void) {
- static char szField[25];
- int nIdx, nCtrlIdx;
-
- pszAppName = "Settings";
- pszTitle = myGetProfileStringDup("Title");
- pszCancelButtonText = myGetProfileStringDup("CancelButtonText");
- pszNextButtonText = myGetProfileStringDup("NextButtonText");
- pszBackButtonText = myGetProfileStringDup("BackButtonText");
-
- nNumFields = myGetProfileInt("NumFields", 0);
-
- nRectId = myGetProfileInt("Rect", DEFAULT_RECT);
-
- bBackEnabled = myGetProfileInt("BackEnabled", -1);
- // by ORTIM: 13-August-2002
- bCancelEnabled = myGetProfileInt("CancelEnabled", -1);
- bCancelShow = myGetProfileInt("CancelShow", -1);
-
- bRTL = myGetProfileInt("RTL", 0);
-
- if (nNumFields > 0) {
- // make this twice as large for the worst case that every control is a browse button.
- // the structure is small enough that this won't waste much memory.
- // if the structure gets much larger, we should switch to a linked list.
- pFields = (FieldType *)MALLOC(sizeof(FieldType)*2*nNumFields);
- }
-
- for (nIdx = 0, nCtrlIdx = 0; nCtrlIdx < nNumFields; nCtrlIdx++, nIdx++) {
- // Control types
- static TableEntry TypeTable[] = {
- { "LABEL", FIELD_LABEL },
- { "TEXT", FIELD_TEXT },
- { "PASSWORD", FIELD_TEXT },
- { "LISTBOX", FIELD_LISTBOX },
- { "COMBOBOX", FIELD_COMBOBOX },
- { "DROPLIST", FIELD_COMBOBOX },
- { "FILEREQUEST", FIELD_FILEREQUEST },
- { "DIRREQUEST", FIELD_DIRREQUEST },
- { "CHECKBOX", FIELD_CHECKBOX },
- { "RADIOBUTTON", FIELD_RADIOBUTTON },
- { "ICON", FIELD_ICON },
- { "BITMAP", FIELD_BITMAP },
- { "GROUPBOX", FIELD_GROUPBOX },
-#ifdef IO_ENABLE_LINK
- { "LINK", FIELD_LINK },
-#else
- { "LINK", FIELD_LABEL },
-#endif
- { "BUTTON", FIELD_BUTTON },
- { "HLINE", FIELD_HLINE },
- { "VLINE", FIELD_VLINE },
- { NULL, 0 }
- };
- // Control flags
- static TableEntry FlagTable[] = {
- { "NOTIFY", LBS_NOTIFY },
- { "WARN_IF_EXIST", OFN_OVERWRITEPROMPT },
- { "FILE_HIDEREADONLY", OFN_HIDEREADONLY },
- { "MULTISELECT", LBS_MULTIPLESEL },
- { "READONLY", FLAG_READONLY },
- { "RIGHT", BS_LEFTTEXT },
- { "PASSWORD", FLAG_PASSWORD },
- { "ONLY_NUMBERS", FLAG_ONLYNUMBERS },
- { "MULTILINE", FLAG_MULTILINE },
- { "NOWORDWRAP", FLAG_NOWORDWRAP },
- { "WANTRETURN", FLAG_WANTRETURN },
- { "EXTENDEDSELCT", LBS_EXTENDEDSEL },
- { "PATH_MUST_EXIST", OFN_PATHMUSTEXIST },
- { "FILE_MUST_EXIST", OFN_FILEMUSTEXIST },
- { "PROMPT_CREATE", OFN_CREATEPROMPT },
- { "DROPLIST", FLAG_DROPLIST },
- { "RESIZETOFIT", FLAG_RESIZETOFIT },
- { "NOTABSTOP", WS_TABSTOP },
- { "GROUP", WS_GROUP },
- { "REQ_SAVE", FLAG_SAVEAS },
- { "FILE_EXPLORER", OFN_EXPLORER },
- { "HSCROLL", WS_HSCROLL },
- { "VSCROLL", WS_VSCROLL },
- { "DISABLED", WS_DISABLED },
- { "TRANSPARENT", TRANSPARENT_BMP },
- { "FOCUS", FLAG_FOCUS },
- { NULL, 0 }
- };
- FieldType *pField = pFields + nIdx;
-
- pField->nField = nCtrlIdx + 1;
- pField->pszHwndEntry = "HWND";
-
- wsprintf(szField, "Field %d", nCtrlIdx + 1);
- pszAppName = szField;
-
- // Get the control type
- myGetProfileString("TYPE");
- pField->nType = LookupToken(TypeTable, szResult);
- if (pField->nType == FIELD_INVALID)
- continue;
-
- // Lookup flags associated with the control type
- pField->nFlags = LookupToken(FlagTable, szResult);
- myGetProfileString("Flags");
- pField->nFlags |= LookupTokens(FlagTable, szResult);
-
- // pszState must not be NULL!
- myGetProfileString("State");
- pField->pszState = strdup(szResult);
-
- // ListBox items list
- {
- int nResult = myGetProfileString("ListItems");
- if (nResult) {
- // add an extra | character to the end to simplify the loop where we add the items.
- pField->pszListItems = (char*)MALLOC(nResult + 2);
- strcpy(pField->pszListItems, szResult);
- pField->pszListItems[nResult] = '|';
- pField->pszListItems[nResult + 1] = '\0';
- }
- }
-
- // Label Text - convert newline
- pField->pszText = myGetProfileStringDup("TEXT");
- if (pField->nType == FIELD_LABEL || pField->nType == FIELD_LINK)
- ConvertNewLines(pField->pszText);
-
- // Dir request - root folder
- pField->pszRoot = myGetProfileStringDup("ROOT");
-
- // ValidateText - convert newline
- pField->pszValidateText = myGetProfileStringDup("ValidateText");
- ConvertNewLines(pField->pszValidateText);
-
- {
- int nResult = GetPrivateProfileString(szField, "Filter", "All Files|*.*", szResult, sizeof(szResult), pszFilename);
- if (nResult) {
- // Convert the filter to the format required by Windows: NULL after each
- // item followed by a terminating NULL
- pField->pszFilter = (char*)MALLOC(nResult + 2);
- strcpy(pField->pszFilter, szResult);
- char *pszPos = pField->pszFilter;
- while (*pszPos)
- {
- if (*pszPos == '|')
- *pszPos++ = 0;
- else
- pszPos = CharNext(pszPos);
- }
- }
- }
-
- pField->rect.left = myGetProfileInt("LEFT", 0);
- pField->rect.top = myGetProfileInt("TOP", 0);
- pField->rect.right = myGetProfileInt("RIGHT", 0);
- pField->rect.bottom = myGetProfileInt("BOTTOM", 0);
- pField->nMinLength = myGetProfileInt("MinLen", 0);
- pField->nMaxLength = myGetProfileInt("MaxLen", 0);
-
- // Text color for LINK control, default is pure blue
- pField->hImage = (HANDLE)myGetProfileInt("TxtColor", RGB(0,0,255));
-
- pField->nControlID = 1200 + nIdx;
- if (pField->nType == FIELD_FILEREQUEST || pField->nType == FIELD_DIRREQUEST)
- {
- FieldType *pNewField = &pFields[nIdx+1];
- pNewField->nControlID = 1200 + nIdx + 1;
- pNewField->nType = FIELD_BROWSEBUTTON;
- pNewField->nFlags = pField->nFlags & (WS_DISABLED | WS_TABSTOP);
- pNewField->pszText = STRDUP(szBrowseButtonCaption); // needed for generic FREE
- pNewField->rect.right = pField->rect.right;
- pNewField->rect.left = pNewField->rect.right - BROWSE_WIDTH;
- pNewField->rect.bottom = pField->rect.bottom;
- pNewField->rect.top = pField->rect.top;
- pField->rect.right = pNewField->rect.left - 3;
- pNewField->nField = nCtrlIdx + 1;
- pNewField->pszHwndEntry = "HWND2";
- nNumFields++;
- nIdx++;
- }
- }
-
- return nNumFields;
-}
-
-LRESULT WINAPI WMCommandProc(HWND hWnd, UINT id, HWND hwndCtl, UINT codeNotify) {
- int nIdx = FindControlIdx(id);
- // Ignore if the dialog is in the process of being created
- if (g_done || nIdx < 0)
- return 0;
-
- switch (pFields[nIdx].nType)
- {
- case FIELD_BROWSEBUTTON:
- --nIdx;
- case FIELD_LINK:
- case FIELD_BUTTON:
- case FIELD_CHECKBOX:
- case FIELD_RADIOBUTTON:
- if (codeNotify != BN_CLICKED)
- return 0;
- break;
- case FIELD_COMBOBOX:
- case FIELD_LISTBOX:
- if (codeNotify != LBN_SELCHANGE) // LBN_SELCHANGE == CBN_SELCHANGE
- return 0;
- break;
- default:
- return 0;
- }
-
- FieldType *pField = pFields + nIdx;
-
- char szBrowsePath[MAX_PATH];
-
- 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:
- GetCurrentDirectory(BUFFER_SIZE, szResult); // save working dir
- if ((pField->nFlags & FLAG_SAVEAS) ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn)) {
- mySetWindowText(pField->hwnd, szBrowsePath);
- SetCurrentDirectory(szResult); // restore working dir
- // OFN_NOCHANGEDIR doesn't always work (see MSDN)
- break;
- }
- else if (szBrowsePath[0] && CommDlgExtendedError() == FNERR_INVALIDFILENAME) {
- szBrowsePath[0] = '\0';
- goto tryagain;
- }
-
- break;
- }
-
- 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)) {
- mySetWindowText(pField->hwnd, szBrowsePath);
- }
-
- CoTaskMemFree(pResult);
-
- break;
- }
-
- case FIELD_LINK:
- case FIELD_BUTTON:
- // Allow the state to be empty - this might be useful in conjunction
- // with the NOTIFY flag
- if (*pField->pszState)
- ShellExecute(hMainWindow, NULL, pField->pszState, NULL, NULL, SW_SHOWDEFAULT);
- break;
- }
-
- if (pField->nFlags & LBS_NOTIFY) {
- // Remember which control was activated then pretend the user clicked Next
- g_NotifyField = nIdx + 1;
- mySendMessage(hMainWindow, WM_NOTIFY_OUTER_NEXT, 1, 0);
- }
-
- return 0;
-}
-
-
-static void *lpWndProcOld;
-
-int g_is_cancel,g_is_back;
-
-BOOL CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- BOOL bRes;
- if (message == WM_NOTIFY_OUTER_NEXT && wParam == 1)
- {
- // Don't call leave function if fields aren't valid
- if (!g_NotifyField && !ValidateFields())
- return 0;
- // Get the settings ready for the leave function verification
- SaveSettings();
- // Reset the record of activated control
- g_NotifyField = 0;
- }
- bRes = CallWindowProc((long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))lpWndProcOld,hwnd,message,wParam,lParam);
- if (message == WM_NOTIFY_OUTER_NEXT && !bRes)
- {
- // if leave function didn't abort (bRes != 0 in that case)
- if (wParam == (WPARAM)-1)
- g_is_back++;
- if (wParam == NOTIFY_BYE_BYE)
- g_is_cancel++;
- g_done++;
- PostMessage(hConfigWindow,WM_CLOSE,0,0);
- }
- return bRes;
-}
-
-BOOL CALLBACK cfgDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg)
- {
- HANDLE_MSG(hwndDlg, WM_COMMAND, WMCommandProc);
- case WM_DRAWITEM:
- {
- DRAWITEMSTRUCT* lpdis = (DRAWITEMSTRUCT*)lParam;
- int nIdx = FindControlIdx(lpdis->CtlID);
-#ifdef IO_LINK_UNDERLINED
- HFONT OldFont;
- LOGFONT lf;
-#endif
-
- if (nIdx < 0)
- break;
- FieldType *pField = pFields + nIdx;
-
-#ifdef IO_LINK_UNDERLINED
- GetObject(GetCurrentObject(lpdis->hDC, OBJ_FONT), sizeof(lf), &lf);
- lf.lfUnderline = TRUE;
- OldFont = (HFONT)SelectObject(lpdis->hDC, CreateFontIndirect(&lf));
-#endif
-
- // We need lpdis->rcItem later
- RECT rc = lpdis->rcItem;
-
- // Calculate needed size of the control
- DrawText(lpdis->hDC, pField->pszText, -1, &rc, DT_VCENTER | DT_WORDBREAK | DT_CALCRECT);
-
- // Make some more room so the focus rect won't cut letters off
- rc.right = min(rc.right + 2, lpdis->rcItem.right);
-
- // Move rect to right if in RTL mode
- if (bRTL)
- {
- rc.left += lpdis->rcItem.right - rc.right;
- rc.right += lpdis->rcItem.right - rc.right;
- }
-
- if (lpdis->itemAction & ODA_DRAWENTIRE)
- {
- // Get TxtColor unless the user has set another using SetCtlColors
- if (!GetWindowLong(lpdis->hwndItem, GWL_USERDATA))
- SetTextColor(lpdis->hDC, (COLORREF) pField->hImage);
-
- // Draw the text
- DrawText(lpdis->hDC, pField->pszText, -1, &rc, DT_CENTER | DT_VCENTER | DT_WORDBREAK | (bRTL ? DT_RTLREADING : 0));
- }
-
- // Draw the focus rect if needed
- if (((lpdis->itemState & ODS_FOCUS) && (lpdis->itemAction & ODA_DRAWENTIRE)) || (lpdis->itemAction & ODA_FOCUS))
- {
- // NB: when not in DRAWENTIRE mode, this will actually toggle the focus
- // rectangle since it's drawn in a XOR way
- DrawFocusRect(lpdis->hDC, &rc);
- }
-
- pField->rect = rc;
-
-#ifdef IO_LINK_UNDERLINED
- DeleteObject(SelectObject(lpdis->hDC, OldFont));
-#endif
- break;
- }
- case WM_CTLCOLORSTATIC:
- case WM_CTLCOLOREDIT:
- case WM_CTLCOLORDLG:
- case WM_CTLCOLORBTN:
- case WM_CTLCOLORLISTBOX:
- // let the NSIS window handle colors, it knows best
- return mySendMessage(hMainWindow, uMsg, wParam, lParam);
- }
- return 0;
-}
-
-#ifdef IO_ENABLE_LINK
-
-#ifndef IDC_HAND
-#define IDC_HAND MAKEINTRESOURCE(32649)
-#endif
-
-#ifndef BS_TYPEMASK
-#define BS_TYPEMASK 0x0000000FL
-#endif
-
-// pFields[nIdx].nParentIdx is used to store original windowproc
-int WINAPI StaticLINKWindowProc(HWND hWin, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- int StaticField = FindControlIdx(GetDlgCtrlID(hWin));
- if (StaticField < 0)
- return 0;
- FieldType *pField = pFields + StaticField;
-
- switch(uMsg)
- {
- case WM_GETDLGCODE:
- // Pretend we are a normal button/default button as appropriate
- return DLGC_BUTTON | ((pField->nFlags & FLAG_WANTRETURN) ? DLGC_DEFPUSHBUTTON : DLGC_UNDEFPUSHBUTTON);
-
- case BM_SETSTYLE:
- // Detect when we are becoming the default button but don't lose the owner-draw style
- if ((wParam & BS_TYPEMASK) == BS_DEFPUSHBUTTON)
- pField->nFlags |= FLAG_WANTRETURN; // Hijack this flag to indicate default button status
- else
- pField->nFlags &= ~FLAG_WANTRETURN;
- wParam = (wParam & ~BS_TYPEMASK) | BS_OWNERDRAW;
- break;
-
- case WM_NCHITTEST:
- {
- POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
- MapWindowPoints(0, hWin, &pt, 1);
- if (PtInRect(&pField->rect, pt))
- return HTCLIENT;
- else
- return HTNOWHERE;
- }
-
- case WM_SETCURSOR:
- {
- if ((HWND)wParam == hWin && LOWORD(lParam) == HTCLIENT)
- {
- HCURSOR hCur = LoadCursor(NULL, IDC_HAND);
- if (hCur)
- {
- SetCursor(hCur);
- return 1; // halt further processing
- }
- }
- }
- }
- return CallWindowProc((WNDPROC)pField->nParentIdx, hWin, uMsg, wParam, lParam);
-}
-#endif
-
-int WINAPI NumbersOnlyPasteWndProc(HWND hWin, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- int nIdx = FindControlIdx(GetDlgCtrlID(hWin));
- if (nIdx < 0)
- return 0;
-
- FieldType *pField = pFields + nIdx;
-
- if (uMsg == WM_PASTE)
- {
- if (OpenClipboard(hWin))
- {
- HGLOBAL hData = GetClipboardData(CF_TEXT);
-
- if (hData)
- {
- char *lpData = (char *) GlobalLock(hData);
- if (lpData)
- {
- int iLen = lstrlen(lpData);
- char *lpFilteredData = (char *) MALLOC(iLen + 1);
-
- if (lpFilteredData)
- {
- for (int i = 0, j = 0; i < iLen; i++)
- {
- if (lpData[i] >= '0' && lpData[i] <= '9')
- {
- lpFilteredData[j] = lpData[i];
- j++;
- }
- lpFilteredData[j] = 0;
- }
-
- SendMessage(hWin, EM_REPLACESEL, TRUE, (LPARAM) lpFilteredData);
- FREE(lpFilteredData);
- }
-
- GlobalUnlock(hData);
- }
- }
-
- CloseClipboard();
-
- return 0;
- }
- }
-
- return CallWindowProc((WNDPROC) pField->wndProc, hWin, uMsg, wParam, lParam);
-}
-
-int old_cancel_visible;
-
-int WINAPI createCfgDlg()
-{
- g_is_back=0;
- g_is_cancel=0;
-
- HWND mainwnd = hMainWindow;
- if (!mainwnd)
- {
- popstring(NULL);
- pushstring("error finding mainwnd");
- return 1; // cannot be used in silent mode unfortunately.
- }
-
- if (!g_stacktop || !*g_stacktop || !(pszFilename = (*g_stacktop)->text) || !pszFilename[0] || !ReadSettings())
- {
- popstring(NULL);
- pushstring("error finding config");
- return 1;
- }
-
- HWND childwnd=GetDlgItem(mainwnd,nRectId);
- if (!childwnd)
- {
- popstring(NULL);
- pushstring("error finding childwnd");
- return 1;
- }
-
- hCancelButton = GetDlgItem(mainwnd,IDCANCEL);
- hNextButton = GetDlgItem(mainwnd,IDOK);
- hBackButton = GetDlgItem(mainwnd,3);
-
- mySetWindowText(hCancelButton,pszCancelButtonText);
- mySetWindowText(hNextButton,pszNextButtonText);
- mySetWindowText(hBackButton,pszBackButtonText);
-
- if (bBackEnabled!=-1) EnableWindow(hBackButton,bBackEnabled);
- if (bCancelEnabled!=-1)
- {
- EnableWindow(hCancelButton,bCancelEnabled);
- if (bCancelEnabled)
- EnableMenuItem(GetSystemMenu(mainwnd, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
- else
- EnableMenuItem(GetSystemMenu(mainwnd, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
- }
- if (bCancelShow!=-1) old_cancel_visible=ShowWindow(hCancelButton,bCancelShow?SW_SHOWNA:SW_HIDE);
-
- HFONT hFont = (HFONT)mySendMessage(mainwnd, WM_GETFONT, 0, 0);
-
- // Prevent WM_COMMANDs from being processed while we are building
- g_done = 1;
-
- int mainWndWidth, mainWndHeight;
- hConfigWindow=CreateDialog(m_hInstance,MAKEINTRESOURCE(IDD_DIALOG1),mainwnd,cfgDlgProc);
- if (hConfigWindow)
- {
- RECT dialog_r;
- GetWindowRect(childwnd,&dialog_r);
- MapWindowPoints(0, mainwnd, (LPPOINT) &dialog_r, 2);
- mainWndWidth = dialog_r.right - dialog_r.left;
- mainWndHeight = dialog_r.bottom - dialog_r.top;
- SetWindowPos(
- hConfigWindow,
- 0,
- dialog_r.left,
- dialog_r.top,
- mainWndWidth,
- mainWndHeight,
- SWP_NOZORDER|SWP_NOACTIVATE
- );
- // Sets the font of IO window to be the same as the main window
- mySendMessage(hConfigWindow, WM_SETFONT, (WPARAM)hFont, TRUE);
- }
- else
- {
- popstring(NULL);
- pushstring("error creating dialog");
- return 1;
- }
-
- BOOL fFocused = FALSE;
- BOOL fFocusedByFlag = FALSE;
-
-#define DEFAULT_STYLES (WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS)
-#define RTL_EX_STYLES (WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR)
-
- for (int nIdx = 0; nIdx < nNumFields; nIdx++) {
- static struct {
- char* pszClass;
- DWORD dwStyle;
- DWORD dwRTLStyle;
- DWORD dwExStyle;
- DWORD dwRTLExStyle;
- } ClassTable[] = {
- { "STATIC", // FIELD_HLINE
- DEFAULT_STYLES | SS_ETCHEDHORZ | SS_SUNKEN,
- DEFAULT_STYLES | SS_ETCHEDHORZ | SS_SUNKEN,
- WS_EX_TRANSPARENT,
- WS_EX_TRANSPARENT | RTL_EX_STYLES },
- { "STATIC", // FIELD_VLINE
- DEFAULT_STYLES | SS_ETCHEDVERT | SS_SUNKEN,
- DEFAULT_STYLES | SS_ETCHEDVERT | SS_SUNKEN,
- WS_EX_TRANSPARENT,
- WS_EX_TRANSPARENT | RTL_EX_STYLES },
- { "STATIC", // FIELD_LABEL
- DEFAULT_STYLES,
- DEFAULT_STYLES | SS_RIGHT,
- WS_EX_TRANSPARENT,
- WS_EX_TRANSPARENT | RTL_EX_STYLES },
- { "STATIC", // FIELD_ICON
- DEFAULT_STYLES | SS_ICON,
- DEFAULT_STYLES | SS_ICON,
- 0,
- RTL_EX_STYLES },
- { "STATIC", // FIELD_BITMAP
- DEFAULT_STYLES | SS_BITMAP,
- DEFAULT_STYLES | SS_BITMAP,
- 0,
- RTL_EX_STYLES },
- { "BUTTON", // FIELD_BROWSEBUTTON
- DEFAULT_STYLES | WS_TABSTOP,
- DEFAULT_STYLES | WS_TABSTOP,
- 0,
- RTL_EX_STYLES },
- { "BUTTON", // FIELD_LINK
- DEFAULT_STYLES | WS_TABSTOP | BS_OWNERDRAW,
- DEFAULT_STYLES | WS_TABSTOP | BS_OWNERDRAW | BS_RIGHT,
- 0,
- RTL_EX_STYLES },
- { "BUTTON", // FIELD_BUTTON
- DEFAULT_STYLES | WS_TABSTOP,
- DEFAULT_STYLES | WS_TABSTOP,
- 0,
- RTL_EX_STYLES },
- { "BUTTON", // FIELD_GROUPBOX
- DEFAULT_STYLES | BS_GROUPBOX,
- DEFAULT_STYLES | BS_GROUPBOX | BS_RIGHT,
- WS_EX_TRANSPARENT,
- WS_EX_TRANSPARENT | RTL_EX_STYLES },
- { "BUTTON", // FIELD_CHECKBOX
- DEFAULT_STYLES | WS_TABSTOP | BS_TEXT | BS_VCENTER | BS_AUTOCHECKBOX | BS_MULTILINE,
- DEFAULT_STYLES | WS_TABSTOP | BS_TEXT | BS_VCENTER | BS_AUTOCHECKBOX | BS_MULTILINE | BS_RIGHT | BS_LEFTTEXT,
- 0,
- RTL_EX_STYLES },
- { "BUTTON", // FIELD_RADIOBUTTON
- DEFAULT_STYLES | WS_TABSTOP | BS_TEXT | BS_VCENTER | BS_AUTORADIOBUTTON | BS_MULTILINE,
- DEFAULT_STYLES | WS_TABSTOP | BS_TEXT | BS_VCENTER | BS_AUTORADIOBUTTON | BS_MULTILINE | BS_RIGHT | BS_LEFTTEXT,
- 0,
- RTL_EX_STYLES },
- { "EDIT", // FIELD_TEXT
- DEFAULT_STYLES | WS_TABSTOP | ES_AUTOHSCROLL,
- DEFAULT_STYLES | WS_TABSTOP | ES_AUTOHSCROLL | ES_RIGHT,
- WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
- WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | RTL_EX_STYLES },
- { "EDIT", // FIELD_FILEREQUEST
- DEFAULT_STYLES | WS_TABSTOP | ES_AUTOHSCROLL,
- DEFAULT_STYLES | WS_TABSTOP | ES_AUTOHSCROLL | ES_RIGHT,
- WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
- WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | RTL_EX_STYLES },
- { "EDIT", // FIELD_DIRREQUEST
- DEFAULT_STYLES | WS_TABSTOP | ES_AUTOHSCROLL,
- DEFAULT_STYLES | WS_TABSTOP | ES_AUTOHSCROLL | ES_RIGHT,
- WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
- WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | RTL_EX_STYLES },
- { "COMBOBOX", // FIELD_COMBOBOX
- DEFAULT_STYLES | WS_TABSTOP | WS_VSCROLL | WS_CLIPCHILDREN | CBS_AUTOHSCROLL | CBS_HASSTRINGS,
- DEFAULT_STYLES | WS_TABSTOP | WS_VSCROLL | WS_CLIPCHILDREN | CBS_AUTOHSCROLL | CBS_HASSTRINGS,
- WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
- WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_RIGHT | RTL_EX_STYLES },
- { "LISTBOX", // FIELD_LISTBOX
- DEFAULT_STYLES | WS_TABSTOP | WS_VSCROLL | LBS_DISABLENOSCROLL | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT,
- DEFAULT_STYLES | WS_TABSTOP | WS_VSCROLL | LBS_DISABLENOSCROLL | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT,
- WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
- WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_RIGHT | RTL_EX_STYLES }
- };
-
- FieldType *pField = pFields + nIdx;
-
-#undef DEFAULT_STYLES
-
- if (pField->nType < 1 || pField->nType > (int)(sizeof(ClassTable) / sizeof(ClassTable[0])))
- continue;
-
- DWORD dwStyle, dwExStyle;
- if (bRTL) {
- dwStyle = ClassTable[pField->nType - 1].dwRTLStyle;
- dwExStyle = ClassTable[pField->nType - 1].dwRTLExStyle;
- }
- else {
- dwStyle = ClassTable[pField->nType - 1].dwStyle;
- dwExStyle = ClassTable[pField->nType - 1].dwExStyle;
- }
-
- // Convert from dialog units
-
- RECT rect = pField->rect;
- // MapDialogRect uses the font used when a dialog is created, and ignores
- // any subsequent WM_SETFONT messages (like we used above); so use the main
- // NSIS window for the conversion, instead of this one.
- MapDialogRect(mainwnd, &rect);
-
- if (pField->rect.left < 0)
- rect.left += mainWndWidth;
- if (pField->rect.right < 0)
- rect.right += mainWndWidth;
- if (pField->rect.top < 0)
- rect.top += mainWndHeight;
- if (pField->rect.bottom < 0)
- rect.bottom += mainWndHeight;
-
- if (bRTL) {
- int right = rect.right;
- rect.right = mainWndWidth - rect.left;
- rect.left = mainWndWidth - right;
- }
-
- 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:
- dwStyle ^= pField->nFlags & BS_LEFTTEXT;
- break;
- case FIELD_TEXT:
- case FIELD_FILEREQUEST:
- case FIELD_DIRREQUEST:
- if (pField->nFlags & FLAG_PASSWORD)
- dwStyle |= ES_PASSWORD;
- if (pField->nFlags & FLAG_ONLYNUMBERS)
- dwStyle |= ES_NUMBER;
- if (pField->nFlags & FLAG_WANTRETURN)
- dwStyle |= ES_WANTRETURN;
- if (pField->nFlags & FLAG_READONLY)
- dwStyle |= ES_READONLY;
- title = pField->pszState;
- if (pField->nFlags & FLAG_MULTILINE)
- {
- dwStyle |= ES_MULTILINE | ES_AUTOVSCROLL;
- // Enable word-wrap unless we have a horizontal scroll bar
- // or it has been explicitly disallowed
- if (!(pField->nFlags & (WS_HSCROLL | FLAG_NOWORDWRAP)))
- dwStyle &= ~ES_AUTOHSCROLL;
- ConvertNewLines(pField->pszState);
- // If multiline-readonly then hold the text back until after the
- // initial focus has been set. This is so the text is not initially
- // selected - useful for License Page look-a-likes.
- if (pField->nFlags & FLAG_READONLY)
- title = NULL;
- }
- break;
- case FIELD_COMBOBOX:
- dwStyle |= (pField->nFlags & FLAG_DROPLIST) ? CBS_DROPDOWNLIST : CBS_DROPDOWN;
- title = pField->pszState;
- break;
- case FIELD_LISTBOX:
- dwStyle |= pField->nFlags & (LBS_NOTIFY | LBS_MULTIPLESEL | LBS_EXTENDEDSEL);
- break;
- }
-
- dwStyle |= pField->nFlags & (WS_GROUP | WS_HSCROLL | WS_VSCROLL | WS_DISABLED);
- if (pField->nFlags & WS_TABSTOP) dwStyle &= ~WS_TABSTOP;
-
- HWND hwCtrl = pField->hwnd = CreateWindowEx(
- dwExStyle,
- ClassTable[pField->nType - 1].pszClass,
- title,
- dwStyle,
- rect.left,
- rect.top,
- rect.right - rect.left,
- rect.bottom - rect.top,
- hConfigWindow,
- (HMENU)pField->nControlID,
- m_hInstance,
- NULL
- );
-
- {
- char szField[64];
- char szHwnd[64];
- wsprintf(szField, "Field %d", pField->nField);
- wsprintf(szHwnd, "%d", hwCtrl);
- WritePrivateProfileString(szField, pField->pszHwndEntry, szHwnd, pszFilename);
- }
-
- if (hwCtrl) {
- // Sets the font of IO window to be the same as the main window
- mySendMessage(hwCtrl, WM_SETFONT, (WPARAM)hFont, TRUE);
- // make sure we created the window, then set additional attributes
- switch (pField->nType) {
- case FIELD_TEXT:
- case FIELD_FILEREQUEST:
- case FIELD_DIRREQUEST:
- mySendMessage(hwCtrl, EM_LIMITTEXT, (WPARAM)pField->nMaxLength, (LPARAM)0);
- if (dwStyle & ES_NUMBER)
- {
- pField->wndProc = GetWindowLong(hwCtrl, GWL_WNDPROC);
- SetWindowLong(hwCtrl, GWL_WNDPROC, (long) NumbersOnlyPasteWndProc);
- }
- 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;
- }
- else {
- nAddMsg = LB_ADDSTRING;
- nFindMsg = LB_FINDSTRINGEXACT;
- nSetSelMsg = LB_SETCURSEL;
- }
- char *pszStart, *pszEnd, *pszList;
- pszStart = pszEnd = pszList = STRDUP(pField->pszListItems);
- // pszListItems has a trailing pipe
- while (*pszEnd) {
- if (*pszEnd == '|') {
- *pszEnd = '\0';
- if (*pszStart)
- mySendMessage(hwCtrl, nAddMsg, 0, (LPARAM) pszStart);
- pszStart = ++pszEnd;
- }
- else
- pszEnd = CharNext(pszEnd);
- }
- FREE(pszList);
- if (pField->pszState) {
- if (pField->nFlags & (LBS_MULTIPLESEL|LBS_EXTENDEDSEL) && nFindMsg == LB_FINDSTRINGEXACT) {
- mySendMessage(hwCtrl, LB_SETSEL, FALSE, (LPARAM)-1);
- pszStart = pszEnd = pField->pszState;
- for (;;) {
- char c = *pszEnd;
- if (c == '|' || c == '\0') {
- *pszEnd = '\0';
- if (*pszStart)
- {
- int nItem = mySendMessage(hwCtrl, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pszStart);
- if (nItem != LB_ERR)
- mySendMessage(hwCtrl, LB_SETSEL, TRUE, nItem);
- }
- if (!c)
- break;
- pszStart = ++pszEnd;
- }
- else
- pszEnd = CharNext(pszEnd);
- }
- }
- else {
- int nItem = mySendMessage(hwCtrl, nFindMsg, (WPARAM)-1, (LPARAM)pField->pszState);
- if (nItem != CB_ERR) { // CB_ERR == LB_ERR == -1
- mySendMessage(hwCtrl, nSetSelMsg, nItem, 0);
- }
- }
- }
- }
- 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));
-
- if ((pField->nFlags & TRANSPARENT_BMP) && nImageType == IMAGE_BITMAP)
- {
- // based on AdvSplash's SetTransparentRegion
- BITMAP bm;
- HBITMAP hBitmap = (HBITMAP) nImage;
-
- if (GetObject(hBitmap, sizeof(bm), &bm))
- {
- HDC dc;
- int x, y;
- HRGN region, cutrgn;
- BITMAPINFO bmi;
- int size = bm.bmWidth * bm.bmHeight * sizeof(int);
- int *bmp = (int *) MALLOC(size);
- if (bmp)
- {
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biHeight = bm.bmHeight;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = bm.bmWidth;
- bmi.bmiHeader.biClrUsed = 0;
- bmi.bmiHeader.biClrImportant = 0;
-
- dc = CreateCompatibleDC(NULL);
- SelectObject(dc, hBitmap);
-
- x = GetDIBits(dc, hBitmap, 0, bm.bmHeight, bmp, &bmi, DIB_RGB_COLORS);
-
- region = CreateRectRgn(0, 0, bm.bmWidth, bm.bmHeight);
-
- int keycolor = *bmp & 0xFFFFFF;
-
- // Search for transparent pixels
- for (y = bm.bmHeight - 1; y >= 0; y--) {
- for (x = 0; x < bm.bmWidth;) {
- if ((*bmp & 0xFFFFFF) == keycolor) {
- int j = x;
- while ((x < bm.bmWidth) && ((*bmp & 0xFFFFFF) == keycolor)) {
- bmp++, x++;
- }
-
- // Cut transparent pixels from the original region
- cutrgn = CreateRectRgn(j, y, x, y + 1);
- CombineRgn(region, region, cutrgn, RGN_XOR);
- DeleteObject(cutrgn);
- } else {
- bmp++, x++;
- }
- }
- }
-
- // Set resulting region.
- SetWindowRgn(hwCtrl, region, TRUE);
- DeleteObject(region);
- DeleteObject(dc);
- FREE(bmp);
- }
- }
- }
-
- mySendMessage(
- hwCtrl,
- STM_SETIMAGE,
- nImageType,
- nImage
- );
-
- if (pField->nType == FIELD_BITMAP)
- {
- // Centre the image in the requested space.
- // Cannot use SS_CENTERIMAGE because it behaves differently on XP to
- // everything else. (Thank you Microsoft.)
- RECT bmp_rect;
- GetClientRect(hwCtrl, &bmp_rect);
- bmp_rect.left = (rect.left + rect.right - bmp_rect.right) / 2;
- bmp_rect.top = (rect.top + rect.bottom - bmp_rect.bottom) / 2;
- SetWindowPos(hwCtrl, NULL, bmp_rect.left, bmp_rect.top, 0, 0,
- SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
- }
-
- break;
- }
-
-#ifdef IO_ENABLE_LINK
- case FIELD_LINK:
- pField->nParentIdx = SetWindowLong(hwCtrl, GWL_WNDPROC, (long)StaticLINKWindowProc);
- break;
-#endif
- }
-
- // Set initial focus to the first appropriate field ( with FOCUS flag)
- if (!fFocusedByFlag && (dwStyle & (WS_TABSTOP | WS_DISABLED)) == WS_TABSTOP && pField->nType >= FIELD_SETFOCUS) {
- if (pField->nFlags & FLAG_FOCUS) {
- fFocusedByFlag = TRUE;
- }
- if (!fFocused || fFocusedByFlag) {
- fFocused = TRUE;
- mySetFocus(hwCtrl);
- }
- }
-
- // If multiline-readonly then hold the text back until after the
- // initial focus has been set. This is so the text is not initially
- // selected - useful for License Page look-a-likes.
- if ((pField->nFlags & (FLAG_MULTILINE | FLAG_READONLY)) == (FLAG_MULTILINE | FLAG_READONLY))
- mySetWindowText(hwCtrl, pField->pszState);
- }
- }
-
- if (!fFocused)
- mySetFocus(hNextButton);
-
- mySetWindowText(mainwnd,pszTitle);
- pFilenameStackEntry = *g_stacktop;
- *g_stacktop = (*g_stacktop)->next;
- static char tmp[32];
- wsprintf(tmp,"%d",hConfigWindow);
- pushstring(tmp);
- return 0;
-}
-
-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
- mySendMessage(hMainWindow, WM_NOTIFY_CUSTOM_READY, (WPARAM)hConfigWindow, 0);
- ShowWindow(hConfigWindow, SW_SHOWNA);
-
- g_done = g_NotifyField = 0;
-
- while (!g_done) {
- MSG msg;
- GetMessage(&msg, NULL, 0, 0);
- if (!IsDialogMessage(hConfigWindow,&msg) && !IsDialogMessage(hMainWindow,&msg))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-
- // we don't save settings on cancel since that means your installer will likely
- // quit soon, which means the ini might get flushed late and cause crap. :) anwyay.
- if (!g_is_cancel) SaveSettings();
-
- SetWindowLong(hMainWindow,DWL_DLGPROC,(long)lpWndProcOld);
- DestroyWindow(hConfigWindow);
-
- // by ORTIM: 13-August-2002
- if (bCancelShow!=-1) ShowWindow(hCancelButton,old_cancel_visible?SW_SHOWNA:SW_HIDE);
-
- FREE(pFilenameStackEntry);
- FREE(pszTitle);
- FREE(pszCancelButtonText);
- FREE(pszNextButtonText);
- FREE(pszBackButtonText);
-
- int i = nNumFields;
- while (i--) {
- FieldType *pField = pFields + i;
-
- int j = FIELD_BUFFERS;
- while (j--)
- FREE(((char **) pField)[j]);
-
- if (pField->nType == FIELD_BITMAP) {
- DeleteObject(pField->hImage);
- }
- if (pField->nType == FIELD_ICON) {
- DestroyIcon((HICON)pField->hImage);
- }
- }
- FREE(pFields);
-
- 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;
- }
- if (createCfgDlg())
- return;
- initCalled++;
-}
-
-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 DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
-{
- m_hInstance=(HINSTANCE) hInst;
- return TRUE;
-}
-
-
-int WINAPI LookupToken(TableEntry* psTable_, char* pszToken_)
-{
- for (int i = 0; psTable_[i].pszName; i++)
- if (!stricmp(pszToken_, psTable_[i].pszName))
- return psTable_[i].nValue;
- return 0;
-}
-
-int WINAPI LookupTokens(TableEntry* psTable_, char* pszTokens_)
-{
- int n = 0;
- char *pszStart = pszTokens_;
- char *pszEnd = pszTokens_;
- for (;;) {
- char c = *pszEnd;
- if (c == '|' || c == '\0') {
- *pszEnd = '\0';
- n |= LookupToken(psTable_, pszStart);
- *pszEnd = c;
- if (!c)
- break;
- pszStart = ++pszEnd;
- }
- else
- pszEnd = CharNext(pszEnd);
- }
- return n;
-}
-
-void WINAPI ConvertNewLines(char *str) {
- char *p1, *p2, *p3;
-
- if (!str)
- return;
-
- p1 = p2 = str;
-
- while (*p1)
- {
- switch (*(LPWORD)p1)
- {
- case CHAR2_TO_WORD('\\', 't'):
- *p2 = '\t';
- p1 += 2;
- p2++;
- break;
- case CHAR2_TO_WORD('\\', 'n'):
- *p2 = '\n';
- p1 += 2;
- p2++;
- break;
- case CHAR2_TO_WORD('\\', 'r'):
- *p2 = '\r';
- p1 += 2;
- p2++;
- break;
- case CHAR2_TO_WORD('\\', '\\'):
- *p2 = '\\';
- p1 += 2;
- p2++;
- break;
- default:
- p3 = CharNext(p1);
- while (p1 < p3)
- *p2++ = *p1++;
- break;
- }
- }
-
- *p2 = 0;
-}
+/*********************************************************
+ *
+ * InstallOptions version 2.0 - Plugin for custom pages
+ *
+ * See Readme.html for documentation and license
+ *
+ *********************************************************/
+
+#include <windows.h>
+#include <windowsx.h>
+#include <shlobj.h>
+#include <commdlg.h>
+#include <cderr.h>
+#include "resource.h"
+#include "shellapi.h"
+
+#define popstring dontuseme
+#include "../ExDLL/exdll.h"
+#undef popstring
+
+// Use for functions only called from one place to possibly reduce some code
+// size. Allows the source code to remain readable by leaving the function
+// intact.
+#ifdef _MSC_VER
+#define INLINE __forceinline
+#else
+#define INLINE inline
+#endif
+
+void *WINAPI MALLOC(int len) { return (void*)GlobalAlloc(GPTR,len); }
+void WINAPI FREE(void *d) { if (d) GlobalFree((HGLOBAL)d); }
+
+void WINAPI popstring(char *str)
+{
+ if (g_stacktop && *g_stacktop)
+ {
+ stack_t *th = *g_stacktop;
+ *g_stacktop = th->next;
+ if (str)
+ lstrcpy(str, th->text);
+ FREE(th);
+ }
+}
+
+#define strcpy(x,y) lstrcpy(x,y)
+//#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))
+
+char *WINAPI STRDUP(const char *c)
+{
+ char *t=(char*)MALLOC(lstrlen(c)+1);
+ return lstrcpy(t,c);
+}
+
+// Turn a pair of chars into a word
+// Turn four chars into a dword
+#ifdef __BIG_ENDIAN__ // Not very likely, but, still...
+#define CHAR2_TO_WORD(a,b) (((WORD)(b))|((a)<<8))
+#define CHAR4_TO_DWORD(a,b,c,d) (((DWORD)CHAR2_TO_WORD(c,d))|(CHAR2_TO_WORD(a,b)<<16))
+#else
+#define CHAR2_TO_WORD(a,b) (((WORD)(a))|((b)<<8))
+#define CHAR4_TO_DWORD(a,b,c,d) (((DWORD)CHAR2_TO_WORD(a,b))|(CHAR2_TO_WORD(c,d)<<16))
+#endif
+
+// Field types
+// NB - the order of this list is important - see below
+
+#define FIELD_INVALID (0)
+#define FIELD_HLINE (1)
+#define FIELD_VLINE (2)
+#define FIELD_LABEL (3)
+#define FIELD_ICON (4)
+#define FIELD_BITMAP (5)
+#define FIELD_BROWSEBUTTON (6)
+#define FIELD_LINK (7)
+#define FIELD_BUTTON (8)
+#define FIELD_GROUPBOX (9)
+#define FIELD_CHECKBOX (10)
+#define FIELD_RADIOBUTTON (11)
+#define FIELD_TEXT (12)
+#define FIELD_FILEREQUEST (13)
+#define FIELD_DIRREQUEST (14)
+#define FIELD_COMBOBOX (15)
+#define FIELD_LISTBOX (16)
+
+#define FIELD_SETFOCUS FIELD_CHECKBOX // First field that qualifies for having the initial keyboard focus
+#define FIELD_CHECKLEN FIELD_TEXT // First field to have length of state value checked against MinLen/MaxLen
+
+//---------------------------------------------------------------------
+// settings
+#define IO_ENABLE_LINK
+
+//#define IO_LINK_UNDERLINED // Uncomment to show links text underlined
+//---------------------------------------------------------------------
+
+// Flags
+
+// LBS_NOTIFY 0x00000001 // LISTBOX/CHECKBOX/RADIOBUTTON/BUTTON/LINK - Notify NSIS script when control is "activated" (exact meaning depends on the type of control)
+// OFN_OVERWRITEPROMPT 0x00000002 // FILEREQUEST
+// OFN_HIDEREADONLY 0x00000004 // FILEREQUEST
+// LBS_MULTIPLESEL 0x00000008 // LISTBOX
+#define FLAG_READONLY 0x00000010 // TEXT/FILEREQUEST/DIRREQUEST
+// BS_LEFTTEXT 0x00000020 // CHECKBOX/RADIOBUTTON
+#define TRANSPARENT_BMP 0x00000020 // BITMAP
+#define FLAG_PASSWORD 0x00000040 // TEXT/FILEREQUEST/DIRREQUEST
+#define FLAG_ONLYNUMBERS 0x00000080 // TEXT/FILEREQUEST/DIRREQUEST
+#define FLAG_MULTILINE 0x00000100 // TEXT/FILEREQUEST/DIRREQUEST
+#define FLAG_NOWORDWRAP 0x00000200 // TEXT/FILEREQUEST/DIRREQUEST - Disable word-wrap in multi-line text boxes
+#define FLAG_WANTRETURN 0x00000400 // TEXT/FILEREQUEST/DIRREQUEST
+// LBS_EXTENDEDSEL 0x00000800 // LISTBOX
+// OFN_PATHMUSTEXIST 0x00000800 // FILEREQUEST
+// OFN_FILEMUSTEXIST 0x00001000 // FILEREQUEST
+// OFN_CREATEPROMPT 0x00002000 // FILEREQUEST
+#define FLAG_DROPLIST 0x00004000 // COMBOBOX
+#define FLAG_RESIZETOFIT 0x00008000 // BITMAP
+// WS_TABSTOP 0x00010000 // *ALL*
+// WS_GROUP 0x00020000 // *ALL*
+#define FLAG_SAVEAS 0x00040000 // FILEREQUEST - Show "Save As" instead of "Open" for FileRequest field
+// OFN_EXPLORER 0x00080000 // FILEREQUEST
+// WS_HSCROLL 0x00100000 // *ALL*
+// WS_VSCROLL 0x00200000 // *ALL*
+// WS_DISABLED 0x08000000 // *ALL*
+#define FLAG_FOCUS 0x10000000 // Controls that can receive focus
+
+struct TableEntry {
+ char *pszName;
+ int nValue;
+};
+
+int WINAPI LookupToken(TableEntry*, char*);
+int WINAPI LookupTokens(TableEntry*, char*);
+
+void WINAPI ConvertNewLines(char *str);
+
+// all allocated buffers must be first in the struct
+// when adding more allocated buffers to FieldType, don't forget to change this define
+#define FIELD_BUFFERS 6
+struct FieldType {
+ char *pszText;
+ char *pszState;
+ char *pszRoot;
+
+ char *pszListItems;
+ char *pszFilter;
+
+ char *pszValidateText;
+ int nMinLength;
+ int nMaxLength;
+
+ int nType;
+ RECT rect;
+
+ int nFlags;
+
+ HWND hwnd;
+ UINT nControlID;
+
+ 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
+
+ int nField; // field number in INI file
+ char *pszHwndEntry; // "HWND" or "HWND2"
+
+ long wndProc;
+};
+
+// initial buffer size. buffers will grow as required.
+// use a value larger than MAX_PATH to prevent need for excessive growing.
+#define BUFFER_SIZE 8192 // 8kb of mem is max char count in multiedit
+
+char szBrowseButtonCaption[] = "...";
+
+HWND hConfigWindow = NULL;
+HWND hMainWindow = NULL;
+HWND hCancelButton = NULL;
+HWND hNextButton = NULL;
+HWND hBackButton = NULL;
+
+HINSTANCE m_hInstance = NULL;
+
+struct _stack_t *pFilenameStackEntry = NULL;
+
+char *pszFilename = NULL;
+char *pszTitle = NULL;
+char *pszCancelButtonText = NULL;
+char *pszNextButtonText = NULL;
+char *pszBackButtonText = NULL;
+
+int bBackEnabled = FALSE;
+int bCancelEnabled = FALSE; // by ORTIM: 13-August-2002
+int bCancelShow = FALSE; // by ORTIM: 13-August-2002
+
+int bRTL = FALSE;
+
+FieldType *pFields = NULL;
+#define DEFAULT_RECT 1018
+int nRectId = 0;
+int nNumFields = 0;
+int g_done;
+int g_NotifyField; // Field number of notifying control
+
+int WINAPI FindControlIdx(UINT id)
+{
+ for (int nIdx = 0; nIdx < nNumFields; nIdx++)
+ if (id == pFields[nIdx].nControlID)
+ return nIdx;
+ return -1;
+}
+
+LRESULT WINAPI mySendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ return SendMessage(hWnd, Msg, wParam, lParam);
+}
+
+void WINAPI mySetFocus(HWND hWnd)
+{
+ mySendMessage(hMainWindow, WM_NEXTDLGCTL, (WPARAM)hWnd, TRUE);
+}
+
+void WINAPI mySetWindowText(HWND hWnd, LPCTSTR pszText)
+{
+ if (pszText)
+ SetWindowText(hWnd, pszText);
+}
+
+int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData) {
+ static TCHAR szDir[MAX_PATH];
+
+ if (uMsg == BFFM_INITIALIZED &&
+ GetWindowText(pFields[(int)pData].hwnd, szDir, MAX_PATH) > 0)
+ mySendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szDir);
+ return 0;
+}
+
+
+bool INLINE ValidateFields() {
+ int nIdx;
+ int nLength;
+
+ // 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 (pField->nType >= FIELD_CHECKLEN) {
+ nLength = mySendMessage(pField->hwnd, WM_GETTEXTLENGTH, 0, 0);
+
+ if (((pField->nMaxLength > 0) && (nLength > pField->nMaxLength)) ||
+ ((pField->nMinLength > 0) && (nLength < pField->nMinLength))) {
+ if (pField->pszValidateText) {
+ char szTitle[1024];
+ GetWindowText(hMainWindow, szTitle, sizeof(szTitle));
+ MessageBox(hConfigWindow, pField->pszValidateText, szTitle, MB_OK|MB_ICONWARNING);
+ }
+ mySetFocus(pField->hwnd);
+ return false;
+ }
+
+ }
+ }
+ return true;
+}
+
+bool WINAPI SaveSettings(void) {
+ static char szField[25];
+ int nBufLen = BUFFER_SIZE;
+ char *pszBuffer = (char*)MALLOC(nBufLen);
+ if (!pszBuffer) return false;
+
+ int nIdx;
+ int CurrField;
+ for (nIdx = 0, CurrField = 1; nIdx < nNumFields; nIdx++, CurrField++) {
+ FieldType *pField = pFields + nIdx;
+ HWND hwnd = pField->hwnd;
+ switch (pField->nType) {
+ case FIELD_BROWSEBUTTON:
+ if (g_NotifyField > CurrField)
+ --g_NotifyField;
+ --CurrField;
+ default:
+ continue;
+
+ case FIELD_CHECKBOX:
+ case FIELD_RADIOBUTTON:
+ wsprintf(pszBuffer, "%d", !!mySendMessage(hwnd, BM_GETCHECK, 0, 0));
+ break;
+
+ case FIELD_LISTBOX:
+ {
+ // Ok, this one requires a bit of work.
+ // First, we allocate a buffer long enough to hold every item.
+ // 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(pField->pszListItems) + 10;
+ if (nLength > nBufLen) {
+ FREE(pszBuffer);
+ nBufLen = nLength;
+ pszBuffer = (char*)MALLOC(nBufLen);
+ if (!pszBuffer) return false;
+ }
+ char *pszItem = (char*)MALLOC(nBufLen);
+ if (!pszItem) return false;
+
+ *pszBuffer = '\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, "|");
+ mySendMessage(hwnd, LB_GETTEXT, (WPARAM)nIdx2, (LPARAM)pszItem);
+ lstrcat(pszBuffer, pszItem);
+ }
+ }
+
+ FREE(pszItem);
+ break;
+ }
+
+ case FIELD_TEXT:
+ case FIELD_FILEREQUEST:
+ case FIELD_DIRREQUEST:
+ case FIELD_COMBOBOX:
+ {
+ int nLength = mySendMessage(pField->hwnd, WM_GETTEXTLENGTH, 0, 0);
+ if (nLength > nBufLen) {
+ FREE(pszBuffer);
+ // add a bit extra so we do this less often
+ nBufLen = nLength + 20;
+ pszBuffer = (char*)MALLOC(nBufLen);
+ if (!pszBuffer) return false;
+ }
+ *pszBuffer='"';
+ GetWindowText(hwnd, pszBuffer+1, nBufLen-1);
+ pszBuffer[nLength+1]='"';
+ pszBuffer[nLength+2]='\0';
+
+ 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;
+ for (p1 = pszBuffer, p2 = pszBuf2; *p1; p1 = CharNext(p1), p2 = CharNext(p2))
+ {
+ switch (*p1) {
+ case '\t':
+ *(LPWORD)p2 = CHAR2_TO_WORD('\\', 't');
+ p2++;
+ break;
+ case '\n':
+ *(LPWORD)p2 = CHAR2_TO_WORD('\\', 'n');
+ p2++;
+ break;
+ case '\r':
+ *(LPWORD)p2 = CHAR2_TO_WORD('\\', 'r');
+ p2++;
+ break;
+ case '\\':
+ *p2++ = '\\';
+ default:
+ lstrcpyn(p2, p1, CharNext(p1) - p1 + 1);
+ break;
+ }
+ }
+ *p2 = 0;
+ nBufLen = nBufLen*2;
+ FREE(pszBuffer);
+ pszBuffer=pszBuf2;
+ }
+ break;
+ }
+ }
+ wsprintf(szField, "Field %d", CurrField);
+ WritePrivateProfileString(szField, "State", pszBuffer, pszFilename);
+ }
+
+ // Tell NSIS which control was activated, if any
+ wsprintf(pszBuffer, "%d", g_NotifyField);
+ WritePrivateProfileString("Settings", "State", pszBuffer, pszFilename);
+
+ FREE(pszBuffer);
+
+ return true;
+}
+
+#define BROWSE_WIDTH 15
+
+static char szResult[BUFFER_SIZE];
+char *pszAppName;
+
+DWORD WINAPI myGetProfileString(LPCTSTR lpKeyName)
+{
+ *szResult = '\0';
+ return GetPrivateProfileString(pszAppName, lpKeyName, "", szResult, BUFFER_SIZE, pszFilename);
+}
+
+char * WINAPI myGetProfileStringDup(LPCTSTR lpKeyName)
+{
+ int nSize = myGetProfileString(lpKeyName);
+ if (nSize)
+ return strdup(szResult);
+ else
+ return NULL;
+}
+
+UINT WINAPI myGetProfileInt(LPCTSTR lpKeyName, INT nDefault)
+{
+ return GetPrivateProfileInt(pszAppName, lpKeyName, nDefault, pszFilename);
+}
+
+int WINAPI ReadSettings(void) {
+ static char szField[25];
+ int nIdx, nCtrlIdx;
+
+ pszAppName = "Settings";
+ pszTitle = myGetProfileStringDup("Title");
+ pszCancelButtonText = myGetProfileStringDup("CancelButtonText");
+ pszNextButtonText = myGetProfileStringDup("NextButtonText");
+ pszBackButtonText = myGetProfileStringDup("BackButtonText");
+
+ nNumFields = myGetProfileInt("NumFields", 0);
+
+ nRectId = myGetProfileInt("Rect", DEFAULT_RECT);
+
+ bBackEnabled = myGetProfileInt("BackEnabled", -1);
+ // by ORTIM: 13-August-2002
+ bCancelEnabled = myGetProfileInt("CancelEnabled", -1);
+ bCancelShow = myGetProfileInt("CancelShow", -1);
+
+ bRTL = myGetProfileInt("RTL", 0);
+
+ if (nNumFields > 0) {
+ // make this twice as large for the worst case that every control is a browse button.
+ // the structure is small enough that this won't waste much memory.
+ // if the structure gets much larger, we should switch to a linked list.
+ pFields = (FieldType *)MALLOC(sizeof(FieldType)*2*nNumFields);
+ }
+
+ for (nIdx = 0, nCtrlIdx = 0; nCtrlIdx < nNumFields; nCtrlIdx++, nIdx++) {
+ // Control types
+ static TableEntry TypeTable[] = {
+ { "LABEL", FIELD_LABEL },
+ { "TEXT", FIELD_TEXT },
+ { "PASSWORD", FIELD_TEXT },
+ { "LISTBOX", FIELD_LISTBOX },
+ { "COMBOBOX", FIELD_COMBOBOX },
+ { "DROPLIST", FIELD_COMBOBOX },
+ { "FILEREQUEST", FIELD_FILEREQUEST },
+ { "DIRREQUEST", FIELD_DIRREQUEST },
+ { "CHECKBOX", FIELD_CHECKBOX },
+ { "RADIOBUTTON", FIELD_RADIOBUTTON },
+ { "ICON", FIELD_ICON },
+ { "BITMAP", FIELD_BITMAP },
+ { "GROUPBOX", FIELD_GROUPBOX },
+#ifdef IO_ENABLE_LINK
+ { "LINK", FIELD_LINK },
+#else
+ { "LINK", FIELD_LABEL },
+#endif
+ { "BUTTON", FIELD_BUTTON },
+ { "HLINE", FIELD_HLINE },
+ { "VLINE", FIELD_VLINE },
+ { NULL, 0 }
+ };
+ // Control flags
+ static TableEntry FlagTable[] = {
+ { "NOTIFY", LBS_NOTIFY },
+ { "WARN_IF_EXIST", OFN_OVERWRITEPROMPT },
+ { "FILE_HIDEREADONLY", OFN_HIDEREADONLY },
+ { "MULTISELECT", LBS_MULTIPLESEL },
+ { "READONLY", FLAG_READONLY },
+ { "RIGHT", BS_LEFTTEXT },
+ { "PASSWORD", FLAG_PASSWORD },
+ { "ONLY_NUMBERS", FLAG_ONLYNUMBERS },
+ { "MULTILINE", FLAG_MULTILINE },
+ { "NOWORDWRAP", FLAG_NOWORDWRAP },
+ { "WANTRETURN", FLAG_WANTRETURN },
+ { "EXTENDEDSELCT", LBS_EXTENDEDSEL },
+ { "PATH_MUST_EXIST", OFN_PATHMUSTEXIST },
+ { "FILE_MUST_EXIST", OFN_FILEMUSTEXIST },
+ { "PROMPT_CREATE", OFN_CREATEPROMPT },
+ { "DROPLIST", FLAG_DROPLIST },
+ { "RESIZETOFIT", FLAG_RESIZETOFIT },
+ { "NOTABSTOP", WS_TABSTOP },
+ { "GROUP", WS_GROUP },
+ { "REQ_SAVE", FLAG_SAVEAS },
+ { "FILE_EXPLORER", OFN_EXPLORER },
+ { "HSCROLL", WS_HSCROLL },
+ { "VSCROLL", WS_VSCROLL },
+ { "DISABLED", WS_DISABLED },
+ { "TRANSPARENT", TRANSPARENT_BMP },
+ { "FOCUS", FLAG_FOCUS },
+ { NULL, 0 }
+ };
+ FieldType *pField = pFields + nIdx;
+
+ pField->nField = nCtrlIdx + 1;
+ pField->pszHwndEntry = "HWND";
+
+ wsprintf(szField, "Field %d", nCtrlIdx + 1);
+ pszAppName = szField;
+
+ // Get the control type
+ myGetProfileString("TYPE");
+ pField->nType = LookupToken(TypeTable, szResult);
+ if (pField->nType == FIELD_INVALID)
+ continue;
+
+ // Lookup flags associated with the control type
+ pField->nFlags = LookupToken(FlagTable, szResult);
+ myGetProfileString("Flags");
+ pField->nFlags |= LookupTokens(FlagTable, szResult);
+
+ // pszState must not be NULL!
+ myGetProfileString("State");
+ pField->pszState = strdup(szResult);
+
+ // ListBox items list
+ {
+ int nResult = myGetProfileString("ListItems");
+ if (nResult) {
+ // add an extra | character to the end to simplify the loop where we add the items.
+ pField->pszListItems = (char*)MALLOC(nResult + 2);
+ strcpy(pField->pszListItems, szResult);
+ pField->pszListItems[nResult] = '|';
+ pField->pszListItems[nResult + 1] = '\0';
+ }
+ }
+
+ // Label Text - convert newline
+ pField->pszText = myGetProfileStringDup("TEXT");
+ if (pField->nType == FIELD_LABEL || pField->nType == FIELD_LINK)
+ ConvertNewLines(pField->pszText);
+
+ // Dir request - root folder
+ pField->pszRoot = myGetProfileStringDup("ROOT");
+
+ // ValidateText - convert newline
+ pField->pszValidateText = myGetProfileStringDup("ValidateText");
+ ConvertNewLines(pField->pszValidateText);
+
+ {
+ int nResult = GetPrivateProfileString(szField, "Filter", "All Files|*.*", szResult, sizeof(szResult), pszFilename);
+ if (nResult) {
+ // Convert the filter to the format required by Windows: NULL after each
+ // item followed by a terminating NULL
+ pField->pszFilter = (char*)MALLOC(nResult + 2);
+ strcpy(pField->pszFilter, szResult);
+ char *pszPos = pField->pszFilter;
+ while (*pszPos)
+ {
+ if (*pszPos == '|')
+ *pszPos++ = 0;
+ else
+ pszPos = CharNext(pszPos);
+ }
+ }
+ }
+
+ pField->rect.left = myGetProfileInt("LEFT", 0);
+ pField->rect.top = myGetProfileInt("TOP", 0);
+ pField->rect.right = myGetProfileInt("RIGHT", 0);
+ pField->rect.bottom = myGetProfileInt("BOTTOM", 0);
+ pField->nMinLength = myGetProfileInt("MinLen", 0);
+ pField->nMaxLength = myGetProfileInt("MaxLen", 0);
+
+ // Text color for LINK control, default is pure blue
+ pField->hImage = (HANDLE)myGetProfileInt("TxtColor", RGB(0,0,255));
+
+ pField->nControlID = 1200 + nIdx;
+ if (pField->nType == FIELD_FILEREQUEST || pField->nType == FIELD_DIRREQUEST)
+ {
+ FieldType *pNewField = &pFields[nIdx+1];
+ pNewField->nControlID = 1200 + nIdx + 1;
+ pNewField->nType = FIELD_BROWSEBUTTON;
+ pNewField->nFlags = pField->nFlags & (WS_DISABLED | WS_TABSTOP);
+ pNewField->pszText = STRDUP(szBrowseButtonCaption); // needed for generic FREE
+ pNewField->rect.right = pField->rect.right;
+ pNewField->rect.left = pNewField->rect.right - BROWSE_WIDTH;
+ pNewField->rect.bottom = pField->rect.bottom;
+ pNewField->rect.top = pField->rect.top;
+ pField->rect.right = pNewField->rect.left - 3;
+ pNewField->nField = nCtrlIdx + 1;
+ pNewField->pszHwndEntry = "HWND2";
+ nNumFields++;
+ nIdx++;
+ }
+ }
+
+ return nNumFields;
+}
+
+LRESULT WINAPI WMCommandProc(HWND hWnd, UINT id, HWND hwndCtl, UINT codeNotify) {
+ int nIdx = FindControlIdx(id);
+ // Ignore if the dialog is in the process of being created
+ if (g_done || nIdx < 0)
+ return 0;
+
+ switch (pFields[nIdx].nType)
+ {
+ case FIELD_BROWSEBUTTON:
+ --nIdx;
+ case FIELD_LINK:
+ case FIELD_BUTTON:
+ case FIELD_CHECKBOX:
+ case FIELD_RADIOBUTTON:
+ if (codeNotify != BN_CLICKED)
+ return 0;
+ break;
+ case FIELD_COMBOBOX:
+ case FIELD_LISTBOX:
+ if (codeNotify != LBN_SELCHANGE) // LBN_SELCHANGE == CBN_SELCHANGE
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+
+ FieldType *pField = pFields + nIdx;
+
+ char szBrowsePath[MAX_PATH];
+
+ 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:
+ GetCurrentDirectory(BUFFER_SIZE, szResult); // save working dir
+ if ((pField->nFlags & FLAG_SAVEAS) ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn)) {
+ mySetWindowText(pField->hwnd, szBrowsePath);
+ SetCurrentDirectory(szResult); // restore working dir
+ // OFN_NOCHANGEDIR doesn't always work (see MSDN)
+ break;
+ }
+ else if (szBrowsePath[0] && CommDlgExtendedError() == FNERR_INVALIDFILENAME) {
+ szBrowsePath[0] = '\0';
+ goto tryagain;
+ }
+
+ break;
+ }
+
+ 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)) {
+ mySetWindowText(pField->hwnd, szBrowsePath);
+ }
+
+ CoTaskMemFree(pResult);
+
+ break;
+ }
+
+ case FIELD_LINK:
+ case FIELD_BUTTON:
+ // Allow the state to be empty - this might be useful in conjunction
+ // with the NOTIFY flag
+ if (*pField->pszState)
+ ShellExecute(hMainWindow, NULL, pField->pszState, NULL, NULL, SW_SHOWDEFAULT);
+ break;
+ }
+
+ if (pField->nFlags & LBS_NOTIFY) {
+ // Remember which control was activated then pretend the user clicked Next
+ g_NotifyField = nIdx + 1;
+ mySendMessage(hMainWindow, WM_NOTIFY_OUTER_NEXT, 1, 0);
+ }
+
+ return 0;
+}
+
+
+static void *lpWndProcOld;
+
+int g_is_cancel,g_is_back;
+
+BOOL CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ BOOL bRes;
+ if (message == WM_NOTIFY_OUTER_NEXT && wParam == 1)
+ {
+ // Don't call leave function if fields aren't valid
+ if (!g_NotifyField && !ValidateFields())
+ return 0;
+ // Get the settings ready for the leave function verification
+ SaveSettings();
+ // Reset the record of activated control
+ g_NotifyField = 0;
+ }
+ bRes = CallWindowProc((long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))lpWndProcOld,hwnd,message,wParam,lParam);
+ if (message == WM_NOTIFY_OUTER_NEXT && !bRes)
+ {
+ // if leave function didn't abort (bRes != 0 in that case)
+ if (wParam == (WPARAM)-1)
+ g_is_back++;
+ if (wParam == NOTIFY_BYE_BYE)
+ g_is_cancel++;
+ g_done++;
+ PostMessage(hConfigWindow,WM_CLOSE,0,0);
+ }
+ return bRes;
+}
+
+BOOL CALLBACK cfgDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ HANDLE_MSG(hwndDlg, WM_COMMAND, WMCommandProc);
+ case WM_DRAWITEM:
+ {
+ DRAWITEMSTRUCT* lpdis = (DRAWITEMSTRUCT*)lParam;
+ int nIdx = FindControlIdx(lpdis->CtlID);
+#ifdef IO_LINK_UNDERLINED
+ HFONT OldFont;
+ LOGFONT lf;
+#endif
+
+ if (nIdx < 0)
+ break;
+ FieldType *pField = pFields + nIdx;
+
+#ifdef IO_LINK_UNDERLINED
+ GetObject(GetCurrentObject(lpdis->hDC, OBJ_FONT), sizeof(lf), &lf);
+ lf.lfUnderline = TRUE;
+ OldFont = (HFONT)SelectObject(lpdis->hDC, CreateFontIndirect(&lf));
+#endif
+
+ // We need lpdis->rcItem later
+ RECT rc = lpdis->rcItem;
+
+ // Calculate needed size of the control
+ DrawText(lpdis->hDC, pField->pszText, -1, &rc, DT_VCENTER | DT_WORDBREAK | DT_CALCRECT);
+
+ // Make some more room so the focus rect won't cut letters off
+ rc.right = min(rc.right + 2, lpdis->rcItem.right);
+
+ // Move rect to right if in RTL mode
+ if (bRTL)
+ {
+ rc.left += lpdis->rcItem.right - rc.right;
+ rc.right += lpdis->rcItem.right - rc.right;
+ }
+
+ if (lpdis->itemAction & ODA_DRAWENTIRE)
+ {
+ // Get TxtColor unless the user has set another using SetCtlColors
+ if (!GetWindowLong(lpdis->hwndItem, GWL_USERDATA))
+ SetTextColor(lpdis->hDC, (COLORREF) pField->hImage);
+
+ // Draw the text
+ DrawText(lpdis->hDC, pField->pszText, -1, &rc, DT_CENTER | DT_VCENTER | DT_WORDBREAK | (bRTL ? DT_RTLREADING : 0));
+ }
+
+ // Draw the focus rect if needed
+ if (((lpdis->itemState & ODS_FOCUS) && (lpdis->itemAction & ODA_DRAWENTIRE)) || (lpdis->itemAction & ODA_FOCUS))
+ {
+ // NB: when not in DRAWENTIRE mode, this will actually toggle the focus
+ // rectangle since it's drawn in a XOR way
+ DrawFocusRect(lpdis->hDC, &rc);
+ }
+
+ pField->rect = rc;
+
+#ifdef IO_LINK_UNDERLINED
+ DeleteObject(SelectObject(lpdis->hDC, OldFont));
+#endif
+ break;
+ }
+ case WM_CTLCOLORSTATIC:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLORLISTBOX:
+ // let the NSIS window handle colors, it knows best
+ return mySendMessage(hMainWindow, uMsg, wParam, lParam);
+ }
+ return 0;
+}
+
+#ifdef IO_ENABLE_LINK
+
+#ifndef IDC_HAND
+#define IDC_HAND MAKEINTRESOURCE(32649)
+#endif
+
+#ifndef BS_TYPEMASK
+#define BS_TYPEMASK 0x0000000FL
+#endif
+
+// pFields[nIdx].nParentIdx is used to store original windowproc
+int WINAPI StaticLINKWindowProc(HWND hWin, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ int StaticField = FindControlIdx(GetDlgCtrlID(hWin));
+ if (StaticField < 0)
+ return 0;
+ FieldType *pField = pFields + StaticField;
+
+ switch(uMsg)
+ {
+ case WM_GETDLGCODE:
+ // Pretend we are a normal button/default button as appropriate
+ return DLGC_BUTTON | ((pField->nFlags & FLAG_WANTRETURN) ? DLGC_DEFPUSHBUTTON : DLGC_UNDEFPUSHBUTTON);
+
+ case BM_SETSTYLE:
+ // Detect when we are becoming the default button but don't lose the owner-draw style
+ if ((wParam & BS_TYPEMASK) == BS_DEFPUSHBUTTON)
+ pField->nFlags |= FLAG_WANTRETURN; // Hijack this flag to indicate default button status
+ else
+ pField->nFlags &= ~FLAG_WANTRETURN;
+ wParam = (wParam & ~BS_TYPEMASK) | BS_OWNERDRAW;
+ break;
+
+ case WM_NCHITTEST:
+ {
+ POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
+ MapWindowPoints(0, hWin, &pt, 1);
+ if (PtInRect(&pField->rect, pt))
+ return HTCLIENT;
+ else
+ return HTNOWHERE;
+ }
+
+ case WM_SETCURSOR:
+ {
+ if ((HWND)wParam == hWin && LOWORD(lParam) == HTCLIENT)
+ {
+ HCURSOR hCur = LoadCursor(NULL, IDC_HAND);
+ if (hCur)
+ {
+ SetCursor(hCur);
+ return 1; // halt further processing
+ }
+ }
+ }
+ }
+ return CallWindowProc((WNDPROC)pField->nParentIdx, hWin, uMsg, wParam, lParam);
+}
+#endif
+
+int WINAPI NumbersOnlyPasteWndProc(HWND hWin, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ int nIdx = FindControlIdx(GetDlgCtrlID(hWin));
+ if (nIdx < 0)
+ return 0;
+
+ FieldType *pField = pFields + nIdx;
+
+ if (uMsg == WM_PASTE)
+ {
+ if (OpenClipboard(hWin))
+ {
+ HGLOBAL hData = GetClipboardData(CF_TEXT);
+
+ if (hData)
+ {
+ char *lpData = (char *) GlobalLock(hData);
+ if (lpData)
+ {
+ int iLen = lstrlen(lpData);
+ char *lpFilteredData = (char *) MALLOC(iLen + 1);
+
+ if (lpFilteredData)
+ {
+ for (int i = 0, j = 0; i < iLen; i++)
+ {
+ if (lpData[i] >= '0' && lpData[i] <= '9')
+ {
+ lpFilteredData[j] = lpData[i];
+ j++;
+ }
+ lpFilteredData[j] = 0;
+ }
+
+ SendMessage(hWin, EM_REPLACESEL, TRUE, (LPARAM) lpFilteredData);
+ FREE(lpFilteredData);
+ }
+
+ GlobalUnlock(hData);
+ }
+ }
+
+ CloseClipboard();
+
+ return 0;
+ }
+ }
+
+ return CallWindowProc((WNDPROC) pField->wndProc, hWin, uMsg, wParam, lParam);
+}
+
+int old_cancel_visible;
+
+int WINAPI createCfgDlg()
+{
+ g_is_back=0;
+ g_is_cancel=0;
+
+ HWND mainwnd = hMainWindow;
+ if (!mainwnd)
+ {
+ popstring(NULL);
+ pushstring("error finding mainwnd");
+ return 1; // cannot be used in silent mode unfortunately.
+ }
+
+ if (!g_stacktop || !*g_stacktop || !(pszFilename = (*g_stacktop)->text) || !pszFilename[0] || !ReadSettings())
+ {
+ popstring(NULL);
+ pushstring("error finding config");
+ return 1;
+ }
+
+ HWND childwnd=GetDlgItem(mainwnd,nRectId);
+ if (!childwnd)
+ {
+ popstring(NULL);
+ pushstring("error finding childwnd");
+ return 1;
+ }
+
+ hCancelButton = GetDlgItem(mainwnd,IDCANCEL);
+ hNextButton = GetDlgItem(mainwnd,IDOK);
+ hBackButton = GetDlgItem(mainwnd,3);
+
+ mySetWindowText(hCancelButton,pszCancelButtonText);
+ mySetWindowText(hNextButton,pszNextButtonText);
+ mySetWindowText(hBackButton,pszBackButtonText);
+
+ if (bBackEnabled!=-1) EnableWindow(hBackButton,bBackEnabled);
+ if (bCancelEnabled!=-1)
+ {
+ EnableWindow(hCancelButton,bCancelEnabled);
+ if (bCancelEnabled)
+ EnableMenuItem(GetSystemMenu(mainwnd, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
+ else
+ EnableMenuItem(GetSystemMenu(mainwnd, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
+ }
+ if (bCancelShow!=-1) old_cancel_visible=ShowWindow(hCancelButton,bCancelShow?SW_SHOWNA:SW_HIDE);
+
+ HFONT hFont = (HFONT)mySendMessage(mainwnd, WM_GETFONT, 0, 0);
+
+ // Prevent WM_COMMANDs from being processed while we are building
+ g_done = 1;
+
+ int mainWndWidth, mainWndHeight;
+ hConfigWindow=CreateDialog(m_hInstance,MAKEINTRESOURCE(IDD_DIALOG1),mainwnd,cfgDlgProc);
+ if (hConfigWindow)
+ {
+ RECT dialog_r;
+ GetWindowRect(childwnd,&dialog_r);
+ MapWindowPoints(0, mainwnd, (LPPOINT) &dialog_r, 2);
+ mainWndWidth = dialog_r.right - dialog_r.left;
+ mainWndHeight = dialog_r.bottom - dialog_r.top;
+ SetWindowPos(
+ hConfigWindow,
+ 0,
+ dialog_r.left,
+ dialog_r.top,
+ mainWndWidth,
+ mainWndHeight,
+ SWP_NOZORDER|SWP_NOACTIVATE
+ );
+ // Sets the font of IO window to be the same as the main window
+ mySendMessage(hConfigWindow, WM_SETFONT, (WPARAM)hFont, TRUE);
+ }
+ else
+ {
+ popstring(NULL);
+ pushstring("error creating dialog");
+ return 1;
+ }
+
+ BOOL fFocused = FALSE;
+ BOOL fFocusedByFlag = FALSE;
+
+#define DEFAULT_STYLES (WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS)
+#define RTL_EX_STYLES (WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR)
+
+ for (int nIdx = 0; nIdx < nNumFields; nIdx++) {
+ static struct {
+ char* pszClass;
+ DWORD dwStyle;
+ DWORD dwRTLStyle;
+ DWORD dwExStyle;
+ DWORD dwRTLExStyle;
+ } ClassTable[] = {
+ { "STATIC", // FIELD_HLINE
+ DEFAULT_STYLES | SS_ETCHEDHORZ | SS_SUNKEN,
+ DEFAULT_STYLES | SS_ETCHEDHORZ | SS_SUNKEN,
+ WS_EX_TRANSPARENT,
+ WS_EX_TRANSPARENT | RTL_EX_STYLES },
+ { "STATIC", // FIELD_VLINE
+ DEFAULT_STYLES | SS_ETCHEDVERT | SS_SUNKEN,
+ DEFAULT_STYLES | SS_ETCHEDVERT | SS_SUNKEN,
+ WS_EX_TRANSPARENT,
+ WS_EX_TRANSPARENT | RTL_EX_STYLES },
+ { "STATIC", // FIELD_LABEL
+ DEFAULT_STYLES,
+ DEFAULT_STYLES | SS_RIGHT,
+ WS_EX_TRANSPARENT,
+ WS_EX_TRANSPARENT | RTL_EX_STYLES },
+ { "STATIC", // FIELD_ICON
+ DEFAULT_STYLES | SS_ICON,
+ DEFAULT_STYLES | SS_ICON,
+ 0,
+ RTL_EX_STYLES },
+ { "STATIC", // FIELD_BITMAP
+ DEFAULT_STYLES | SS_BITMAP,
+ DEFAULT_STYLES | SS_BITMAP,
+ 0,
+ RTL_EX_STYLES },
+ { "BUTTON", // FIELD_BROWSEBUTTON
+ DEFAULT_STYLES | WS_TABSTOP,
+ DEFAULT_STYLES | WS_TABSTOP,
+ 0,
+ RTL_EX_STYLES },
+ { "BUTTON", // FIELD_LINK
+ DEFAULT_STYLES | WS_TABSTOP | BS_OWNERDRAW,
+ DEFAULT_STYLES | WS_TABSTOP | BS_OWNERDRAW | BS_RIGHT,
+ 0,
+ RTL_EX_STYLES },
+ { "BUTTON", // FIELD_BUTTON
+ DEFAULT_STYLES | WS_TABSTOP,
+ DEFAULT_STYLES | WS_TABSTOP,
+ 0,
+ RTL_EX_STYLES },
+ { "BUTTON", // FIELD_GROUPBOX
+ DEFAULT_STYLES | BS_GROUPBOX,
+ DEFAULT_STYLES | BS_GROUPBOX | BS_RIGHT,
+ WS_EX_TRANSPARENT,
+ WS_EX_TRANSPARENT | RTL_EX_STYLES },
+ { "BUTTON", // FIELD_CHECKBOX
+ DEFAULT_STYLES | WS_TABSTOP | BS_TEXT | BS_VCENTER | BS_AUTOCHECKBOX | BS_MULTILINE,
+ DEFAULT_STYLES | WS_TABSTOP | BS_TEXT | BS_VCENTER | BS_AUTOCHECKBOX | BS_MULTILINE | BS_RIGHT | BS_LEFTTEXT,
+ 0,
+ RTL_EX_STYLES },
+ { "BUTTON", // FIELD_RADIOBUTTON
+ DEFAULT_STYLES | WS_TABSTOP | BS_TEXT | BS_VCENTER | BS_AUTORADIOBUTTON | BS_MULTILINE,
+ DEFAULT_STYLES | WS_TABSTOP | BS_TEXT | BS_VCENTER | BS_AUTORADIOBUTTON | BS_MULTILINE | BS_RIGHT | BS_LEFTTEXT,
+ 0,
+ RTL_EX_STYLES },
+ { "EDIT", // FIELD_TEXT
+ DEFAULT_STYLES | WS_TABSTOP | ES_AUTOHSCROLL,
+ DEFAULT_STYLES | WS_TABSTOP | ES_AUTOHSCROLL | ES_RIGHT,
+ WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
+ WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | RTL_EX_STYLES },
+ { "EDIT", // FIELD_FILEREQUEST
+ DEFAULT_STYLES | WS_TABSTOP | ES_AUTOHSCROLL,
+ DEFAULT_STYLES | WS_TABSTOP | ES_AUTOHSCROLL | ES_RIGHT,
+ WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
+ WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | RTL_EX_STYLES },
+ { "EDIT", // FIELD_DIRREQUEST
+ DEFAULT_STYLES | WS_TABSTOP | ES_AUTOHSCROLL,
+ DEFAULT_STYLES | WS_TABSTOP | ES_AUTOHSCROLL | ES_RIGHT,
+ WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
+ WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | RTL_EX_STYLES },
+ { "COMBOBOX", // FIELD_COMBOBOX
+ DEFAULT_STYLES | WS_TABSTOP | WS_VSCROLL | WS_CLIPCHILDREN | CBS_AUTOHSCROLL | CBS_HASSTRINGS,
+ DEFAULT_STYLES | WS_TABSTOP | WS_VSCROLL | WS_CLIPCHILDREN | CBS_AUTOHSCROLL | CBS_HASSTRINGS,
+ WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
+ WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_RIGHT | RTL_EX_STYLES },
+ { "LISTBOX", // FIELD_LISTBOX
+ DEFAULT_STYLES | WS_TABSTOP | WS_VSCROLL | LBS_DISABLENOSCROLL | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT,
+ DEFAULT_STYLES | WS_TABSTOP | WS_VSCROLL | LBS_DISABLENOSCROLL | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT,
+ WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
+ WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_RIGHT | RTL_EX_STYLES }
+ };
+
+ FieldType *pField = pFields + nIdx;
+
+#undef DEFAULT_STYLES
+
+ if (pField->nType < 1 || pField->nType > (int)(sizeof(ClassTable) / sizeof(ClassTable[0])))
+ continue;
+
+ DWORD dwStyle, dwExStyle;
+ if (bRTL) {
+ dwStyle = ClassTable[pField->nType - 1].dwRTLStyle;
+ dwExStyle = ClassTable[pField->nType - 1].dwRTLExStyle;
+ }
+ else {
+ dwStyle = ClassTable[pField->nType - 1].dwStyle;
+ dwExStyle = ClassTable[pField->nType - 1].dwExStyle;
+ }
+
+ // Convert from dialog units
+
+ RECT rect = pField->rect;
+ // MapDialogRect uses the font used when a dialog is created, and ignores
+ // any subsequent WM_SETFONT messages (like we used above); so use the main
+ // NSIS window for the conversion, instead of this one.
+ MapDialogRect(mainwnd, &rect);
+
+ if (pField->rect.left < 0)
+ rect.left += mainWndWidth;
+ if (pField->rect.right < 0)
+ rect.right += mainWndWidth;
+ if (pField->rect.top < 0)
+ rect.top += mainWndHeight;
+ if (pField->rect.bottom < 0)
+ rect.bottom += mainWndHeight;
+
+ if (bRTL) {
+ int right = rect.right;
+ rect.right = mainWndWidth - rect.left;
+ rect.left = mainWndWidth - right;
+ }
+
+ 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:
+ dwStyle ^= pField->nFlags & BS_LEFTTEXT;
+ break;
+ case FIELD_TEXT:
+ case FIELD_FILEREQUEST:
+ case FIELD_DIRREQUEST:
+ if (pField->nFlags & FLAG_PASSWORD)
+ dwStyle |= ES_PASSWORD;
+ if (pField->nFlags & FLAG_ONLYNUMBERS)
+ dwStyle |= ES_NUMBER;
+ if (pField->nFlags & FLAG_WANTRETURN)
+ dwStyle |= ES_WANTRETURN;
+ if (pField->nFlags & FLAG_READONLY)
+ dwStyle |= ES_READONLY;
+ title = pField->pszState;
+ if (pField->nFlags & FLAG_MULTILINE)
+ {
+ dwStyle |= ES_MULTILINE | ES_AUTOVSCROLL;
+ // Enable word-wrap unless we have a horizontal scroll bar
+ // or it has been explicitly disallowed
+ if (!(pField->nFlags & (WS_HSCROLL | FLAG_NOWORDWRAP)))
+ dwStyle &= ~ES_AUTOHSCROLL;
+ ConvertNewLines(pField->pszState);
+ // If multiline-readonly then hold the text back until after the
+ // initial focus has been set. This is so the text is not initially
+ // selected - useful for License Page look-a-likes.
+ if (pField->nFlags & FLAG_READONLY)
+ title = NULL;
+ }
+ break;
+ case FIELD_COMBOBOX:
+ dwStyle |= (pField->nFlags & FLAG_DROPLIST) ? CBS_DROPDOWNLIST : CBS_DROPDOWN;
+ title = pField->pszState;
+ break;
+ case FIELD_LISTBOX:
+ dwStyle |= pField->nFlags & (LBS_NOTIFY | LBS_MULTIPLESEL | LBS_EXTENDEDSEL);
+ break;
+ }
+
+ dwStyle |= pField->nFlags & (WS_GROUP | WS_HSCROLL | WS_VSCROLL | WS_DISABLED);
+ if (pField->nFlags & WS_TABSTOP) dwStyle &= ~WS_TABSTOP;
+
+ HWND hwCtrl = pField->hwnd = CreateWindowEx(
+ dwExStyle,
+ ClassTable[pField->nType - 1].pszClass,
+ title,
+ dwStyle,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ hConfigWindow,
+ (HMENU)pField->nControlID,
+ m_hInstance,
+ NULL
+ );
+
+ {
+ char szField[64];
+ char szHwnd[64];
+ wsprintf(szField, "Field %d", pField->nField);
+ wsprintf(szHwnd, "%d", hwCtrl);
+ WritePrivateProfileString(szField, pField->pszHwndEntry, szHwnd, pszFilename);
+ }
+
+ if (hwCtrl) {
+ // Sets the font of IO window to be the same as the main window
+ mySendMessage(hwCtrl, WM_SETFONT, (WPARAM)hFont, TRUE);
+ // make sure we created the window, then set additional attributes
+ switch (pField->nType) {
+ case FIELD_TEXT:
+ case FIELD_FILEREQUEST:
+ case FIELD_DIRREQUEST:
+ mySendMessage(hwCtrl, EM_LIMITTEXT, (WPARAM)pField->nMaxLength, (LPARAM)0);
+ if (dwStyle & ES_NUMBER)
+ {
+ pField->wndProc = GetWindowLong(hwCtrl, GWL_WNDPROC);
+ SetWindowLong(hwCtrl, GWL_WNDPROC, (long) NumbersOnlyPasteWndProc);
+ }
+ 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;
+ }
+ else {
+ nAddMsg = LB_ADDSTRING;
+ nFindMsg = LB_FINDSTRINGEXACT;
+ nSetSelMsg = LB_SETCURSEL;
+ }
+ char *pszStart, *pszEnd, *pszList;
+ pszStart = pszEnd = pszList = STRDUP(pField->pszListItems);
+ // pszListItems has a trailing pipe
+ while (*pszEnd) {
+ if (*pszEnd == '|') {
+ *pszEnd = '\0';
+ if (*pszStart)
+ mySendMessage(hwCtrl, nAddMsg, 0, (LPARAM) pszStart);
+ pszStart = ++pszEnd;
+ }
+ else
+ pszEnd = CharNext(pszEnd);
+ }
+ FREE(pszList);
+ if (pField->pszState) {
+ if (pField->nFlags & (LBS_MULTIPLESEL|LBS_EXTENDEDSEL) && nFindMsg == LB_FINDSTRINGEXACT) {
+ mySendMessage(hwCtrl, LB_SETSEL, FALSE, (LPARAM)-1);
+ pszStart = pszEnd = pField->pszState;
+ for (;;) {
+ char c = *pszEnd;
+ if (c == '|' || c == '\0') {
+ *pszEnd = '\0';
+ if (*pszStart)
+ {
+ int nItem = mySendMessage(hwCtrl, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pszStart);
+ if (nItem != LB_ERR)
+ mySendMessage(hwCtrl, LB_SETSEL, TRUE, nItem);
+ }
+ if (!c)
+ break;
+ pszStart = ++pszEnd;
+ }
+ else
+ pszEnd = CharNext(pszEnd);
+ }
+ }
+ else {
+ int nItem = mySendMessage(hwCtrl, nFindMsg, (WPARAM)-1, (LPARAM)pField->pszState);
+ if (nItem != CB_ERR) { // CB_ERR == LB_ERR == -1
+ mySendMessage(hwCtrl, nSetSelMsg, nItem, 0);
+ }
+ }
+ }
+ }
+ 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));
+
+ if ((pField->nFlags & TRANSPARENT_BMP) && nImageType == IMAGE_BITMAP)
+ {
+ // based on AdvSplash's SetTransparentRegion
+ BITMAP bm;
+ HBITMAP hBitmap = (HBITMAP) nImage;
+
+ if (GetObject(hBitmap, sizeof(bm), &bm))
+ {
+ HDC dc;
+ int x, y;
+ HRGN region, cutrgn;
+ BITMAPINFO bmi;
+ int size = bm.bmWidth * bm.bmHeight * sizeof(int);
+ int *bmp = (int *) MALLOC(size);
+ if (bmp)
+ {
+ bmi.bmiHeader.biBitCount = 32;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biHeight = bm.bmHeight;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = bm.bmWidth;
+ bmi.bmiHeader.biClrUsed = 0;
+ bmi.bmiHeader.biClrImportant = 0;
+
+ dc = CreateCompatibleDC(NULL);
+ SelectObject(dc, hBitmap);
+
+ x = GetDIBits(dc, hBitmap, 0, bm.bmHeight, bmp, &bmi, DIB_RGB_COLORS);
+
+ region = CreateRectRgn(0, 0, bm.bmWidth, bm.bmHeight);
+
+ int keycolor = *bmp & 0xFFFFFF;
+
+ // Search for transparent pixels
+ for (y = bm.bmHeight - 1; y >= 0; y--) {
+ for (x = 0; x < bm.bmWidth;) {
+ if ((*bmp & 0xFFFFFF) == keycolor) {
+ int j = x;
+ while ((x < bm.bmWidth) && ((*bmp & 0xFFFFFF) == keycolor)) {
+ bmp++, x++;
+ }
+
+ // Cut transparent pixels from the original region
+ cutrgn = CreateRectRgn(j, y, x, y + 1);
+ CombineRgn(region, region, cutrgn, RGN_XOR);
+ DeleteObject(cutrgn);
+ } else {
+ bmp++, x++;
+ }
+ }
+ }
+
+ // Set resulting region.
+ SetWindowRgn(hwCtrl, region, TRUE);
+ DeleteObject(region);
+ DeleteObject(dc);
+ FREE(bmp);
+ }
+ }
+ }
+
+ mySendMessage(
+ hwCtrl,
+ STM_SETIMAGE,
+ nImageType,
+ nImage
+ );
+
+ if (pField->nType == FIELD_BITMAP)
+ {
+ // Centre the image in the requested space.
+ // Cannot use SS_CENTERIMAGE because it behaves differently on XP to
+ // everything else. (Thank you Microsoft.)
+ RECT bmp_rect;
+ GetClientRect(hwCtrl, &bmp_rect);
+ bmp_rect.left = (rect.left + rect.right - bmp_rect.right) / 2;
+ bmp_rect.top = (rect.top + rect.bottom - bmp_rect.bottom) / 2;
+ SetWindowPos(hwCtrl, NULL, bmp_rect.left, bmp_rect.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
+ }
+
+ break;
+ }
+
+#ifdef IO_ENABLE_LINK
+ case FIELD_LINK:
+ pField->nParentIdx = SetWindowLong(hwCtrl, GWL_WNDPROC, (long)StaticLINKWindowProc);
+ break;
+#endif
+ }
+
+ // Set initial focus to the first appropriate field ( with FOCUS flag)
+ if (!fFocusedByFlag && (dwStyle & (WS_TABSTOP | WS_DISABLED)) == WS_TABSTOP && pField->nType >= FIELD_SETFOCUS) {
+ if (pField->nFlags & FLAG_FOCUS) {
+ fFocusedByFlag = TRUE;
+ }
+ if (!fFocused || fFocusedByFlag) {
+ fFocused = TRUE;
+ mySetFocus(hwCtrl);
+ }
+ }
+
+ // If multiline-readonly then hold the text back until after the
+ // initial focus has been set. This is so the text is not initially
+ // selected - useful for License Page look-a-likes.
+ if ((pField->nFlags & (FLAG_MULTILINE | FLAG_READONLY)) == (FLAG_MULTILINE | FLAG_READONLY))
+ mySetWindowText(hwCtrl, pField->pszState);
+ }
+ }
+
+ if (!fFocused)
+ mySetFocus(hNextButton);
+
+ mySetWindowText(mainwnd,pszTitle);
+ pFilenameStackEntry = *g_stacktop;
+ *g_stacktop = (*g_stacktop)->next;
+ static char tmp[32];
+ wsprintf(tmp,"%d",hConfigWindow);
+ pushstring(tmp);
+ return 0;
+}
+
+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
+ mySendMessage(hMainWindow, WM_NOTIFY_CUSTOM_READY, (WPARAM)hConfigWindow, 0);
+ ShowWindow(hConfigWindow, SW_SHOWNA);
+
+ g_done = g_NotifyField = 0;
+
+ while (!g_done) {
+ MSG msg;
+ GetMessage(&msg, NULL, 0, 0);
+ if (!IsDialogMessage(hConfigWindow,&msg) && !IsDialogMessage(hMainWindow,&msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ // we don't save settings on cancel since that means your installer will likely
+ // quit soon, which means the ini might get flushed late and cause crap. :) anwyay.
+ if (!g_is_cancel) SaveSettings();
+
+ SetWindowLong(hMainWindow,DWL_DLGPROC,(long)lpWndProcOld);
+ DestroyWindow(hConfigWindow);
+
+ // by ORTIM: 13-August-2002
+ if (bCancelShow!=-1) ShowWindow(hCancelButton,old_cancel_visible?SW_SHOWNA:SW_HIDE);
+
+ FREE(pFilenameStackEntry);
+ FREE(pszTitle);
+ FREE(pszCancelButtonText);
+ FREE(pszNextButtonText);
+ FREE(pszBackButtonText);
+
+ int i = nNumFields;
+ while (i--) {
+ FieldType *pField = pFields + i;
+
+ int j = FIELD_BUFFERS;
+ while (j--)
+ FREE(((char **) pField)[j]);
+
+ if (pField->nType == FIELD_BITMAP) {
+ DeleteObject(pField->hImage);
+ }
+ if (pField->nType == FIELD_ICON) {
+ DestroyIcon((HICON)pField->hImage);
+ }
+ }
+ FREE(pFields);
+
+ 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;
+ }
+ if (createCfgDlg())
+ return;
+ initCalled++;
+}
+
+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 DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
+{
+ m_hInstance=(HINSTANCE) hInst;
+ return TRUE;
+}
+
+
+int WINAPI LookupToken(TableEntry* psTable_, char* pszToken_)
+{
+ for (int i = 0; psTable_[i].pszName; i++)
+ if (!stricmp(pszToken_, psTable_[i].pszName))
+ return psTable_[i].nValue;
+ return 0;
+}
+
+int WINAPI LookupTokens(TableEntry* psTable_, char* pszTokens_)
+{
+ int n = 0;
+ char *pszStart = pszTokens_;
+ char *pszEnd = pszTokens_;
+ for (;;) {
+ char c = *pszEnd;
+ if (c == '|' || c == '\0') {
+ *pszEnd = '\0';
+ n |= LookupToken(psTable_, pszStart);
+ *pszEnd = c;
+ if (!c)
+ break;
+ pszStart = ++pszEnd;
+ }
+ else
+ pszEnd = CharNext(pszEnd);
+ }
+ return n;
+}
+
+void WINAPI ConvertNewLines(char *str) {
+ char *p1, *p2, *p3;
+
+ if (!str)
+ return;
+
+ p1 = p2 = str;
+
+ while (*p1)
+ {
+ switch (*(LPWORD)p1)
+ {
+ case CHAR2_TO_WORD('\\', 't'):
+ *p2 = '\t';
+ p1 += 2;
+ p2++;
+ break;
+ case CHAR2_TO_WORD('\\', 'n'):
+ *p2 = '\n';
+ p1 += 2;
+ p2++;
+ break;
+ case CHAR2_TO_WORD('\\', 'r'):
+ *p2 = '\r';
+ p1 += 2;
+ p2++;
+ break;
+ case CHAR2_TO_WORD('\\', '\\'):
+ *p2 = '\\';
+ p1 += 2;
+ p2++;
+ break;
+ default:
+ p3 = CharNext(p1);
+ while (p1 < p3)
+ *p2++ = *p1++;
+ break;
+ }
+ }
+
+ *p2 = 0;
+}