| /* |
| * GraphApp - Cross-Platform Graphics Programming Library. |
| * |
| * File: dialogs.c -- standard file dialogs and a few others. |
| * Platform: Windows Version: 2.42 Date: 1998/07/07 |
| * |
| * Version: 1.00 Changes: Original version by Lachlan Patrick. |
| * Version: 1.50 Changes: Uses new rectangles, callbacks. |
| * Version: 2.20 Changes: Handle null strings correctly now. |
| * Version: 2.40 Changes: Now uses YES, NO, CANCEL symbols. |
| * Version: 2.42 Changes: Askstring fixed by Laurent Piguet. |
| */ |
| |
| /* Copyright (C) 1993-1998 Lachlan Patrick |
| |
| This file is part of GraphApp, a cross-platform C graphics library. |
| |
| GraphApp is free software; you can redistribute it and/or modify it |
| under the terms of the GNU Library General Public License. |
| GraphApp is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY. |
| |
| See the file COPYLIB.TXT for details. |
| */ |
| |
| /* Copyright (C) 2004--2008 The R Foundation |
| Copyright (C) 2013--2021 The R Core Team |
| |
| Additions for R, Chris Jackson |
| Find and replace dialog boxes and dialog handlers */ |
| |
| /* Mingw-w64 defines this to be 0x0502 */ |
| #ifndef _WIN32_WINNT |
| # define _WIN32_WINNT 0x0500 |
| #endif |
| |
| #include "win-nls.h" |
| #include "internal.h" |
| #include "ga.h" |
| |
| #include <shlobj.h> |
| |
| typedef struct { |
| char default_str[MAX_PATH]; |
| char question[40]; |
| } browserInfo; |
| |
| #define STATUSTEXT 14146 |
| |
| static int CALLBACK |
| InitBrowseCallbackProc( HWND hwnd, UINT uMsg, LPARAM lp, LPARAM lpData ) |
| { |
| char szDir[MAX_PATH], status[MAX_PATH + 40 + 2]; |
| |
| if (uMsg == BFFM_INITIALIZED) { |
| SendMessage(hwnd, BFFM_SETSELECTION, 1, |
| (LPARAM)&((browserInfo*)lpData)->default_str); |
| } else if (uMsg == BFFM_SELCHANGED) { |
| if (SHGetPathFromIDList((LPITEMIDLIST) lp, szDir)) { |
| snprintf(status, MAX_PATH+40+2, "%s\n %s", |
| ((browserInfo*)lpData)->question, szDir); |
| SetDlgItemText(hwnd, STATUSTEXT, status); |
| SendMessage(hwnd, BFFM_ENABLEOK, 0, TRUE); |
| } else |
| SendMessage(hwnd, BFFM_ENABLEOK, 0, FALSE); |
| } |
| return(0); |
| } |
| |
| #define BUFSIZE _MAX_PATH |
| static char strbuf[BUFSIZE]; |
| static wchar_t wcsbuf[65536]; |
| |
| static const char *filter[] = { |
| "All Files (*.*)", "*.*", |
| "Text Files (*.TXT)", "*.txt", |
| "HTML Files (*.HTM)", "*.htm", |
| "PNG Files (*.PNG)", "*.png", |
| "JPEG Files (*.JPG)", "*.jpg", |
| "BMP Files (*.BMP)", "*.bmp", |
| "" |
| }; |
| |
| static const wchar_t *wfilter[] = { |
| L"All Files (*.*)", L"*.*", |
| L"Text Files (*.TXT)", L"*.txt", |
| L"HTML Files (*.HTM)", L"*.htm", |
| L"PNG Files (*.PNG)", L"*.png", |
| L"JPEG Files (*.JPG)", L"*.jpg", |
| L"BMP Files (*.BMP)", L"*.bmp", |
| L"" |
| }; |
| |
| unsigned int TopmostDialogs = 0; /* May be MB_TOPMOST */ |
| |
| static const char *userfilter; |
| static const wchar_t *userfilterW; |
| |
| void setuserfilter(const char *uf) |
| { |
| userfilter=uf; |
| } |
| |
| void setuserfilterW(const wchar_t *uf) |
| { |
| userfilterW=uf; |
| } |
| |
| static HWND hModelessDlg = NULL; |
| |
| int myMessageBox(HWND h, const char *text, const char *caption, UINT type) |
| { |
| if(localeCP != GetACP()) { |
| wchar_t wc[1000], wcaption[100]; |
| mbstowcs(wcaption, caption, 100); |
| mbstowcs(wc, text, 1000); |
| return MessageBoxW(h, wc, wcaption, type); |
| } else |
| return MessageBoxA(h, text, caption, type); |
| } |
| |
| /* |
| * Error reporting dialog. |
| */ |
| void apperror(const char *errstr) |
| { |
| if (! errstr) |
| errstr = "Unspecified error"; |
| myMessageBox(0, errstr, "Graphics Library Error", |
| MB_TASKMODAL | MB_ICONSTOP | MB_OK | TopmostDialogs); |
| exitapp(); |
| } |
| |
| void askok(const char *info) |
| { |
| if (! info) |
| info = ""; |
| myMessageBox(0, info, "Information", |
| MB_TASKMODAL | MB_ICONINFORMATION | MB_OK | TopmostDialogs); |
| } |
| |
| int askokcancel(const char *question) |
| { |
| int result; |
| |
| if (! question) |
| question = ""; |
| result = myMessageBox(0, question, G_("Question"), |
| MB_TASKMODAL | MB_ICONQUESTION | MB_OKCANCEL | TopmostDialogs); |
| |
| switch (result) { |
| case IDOK: result = YES; break; |
| case IDCANCEL: |
| default: result = CANCEL; break; |
| } |
| return result; |
| } |
| |
| int askyesno(const char *question) |
| { |
| int result; |
| |
| if (! question) |
| question = ""; |
| result = myMessageBox(0, question, G_("Question"), |
| MB_TASKMODAL | MB_ICONQUESTION | MB_YESNO | TopmostDialogs); |
| |
| switch (result) { |
| case IDYES: result = YES; break; |
| case IDNO: result = NO; break; |
| default: result = CANCEL; break; |
| } |
| return result; |
| } |
| |
| int askyesnocancel(const char *question) |
| { |
| int result; |
| |
| if (! question) |
| question = ""; |
| result = myMessageBox(0, question, G_("Question"), |
| MB_TASKMODAL | MB_ICONQUESTION | MB_YESNOCANCEL | MB_SETFOREGROUND | TopmostDialogs); |
| |
| switch (result) { |
| case IDYES: result = YES; break; |
| case IDNO: result = NO; break; |
| case IDCANCEL: |
| default: result = CANCEL; break; |
| } |
| return result; |
| } |
| |
| /* This should always have a native encoded name, so don't need Unicode here */ |
| static char cod[MAX_PATH]=""; /*current open directory*/ |
| |
| void askchangedir() |
| { |
| char *s, msg[MAX_PATH + 40]; |
| |
| /* set cod to current directory */ |
| GetCurrentDirectory(MAX_PATH, cod); |
| s = askcdstring(G_(" Change working directory to:"), cod); |
| if (s && (SetCurrentDirectory(s) == FALSE)) { |
| snprintf(msg, MAX_PATH + 40, |
| G_("Unable to set '%s' as working directory"), s); |
| askok(msg); |
| } |
| /* in every case reset cod (to new directory if all went ok |
| or to old since user may have edited it) */ |
| GetCurrentDirectory(MAX_PATH, cod); |
| } |
| |
| char *askfilename(const char *title, const char *default_name) |
| { |
| if (*askfilenames(title, default_name, 0, userfilter?userfilter:filter[0], 0, |
| strbuf, BUFSIZE, NULL)) return strbuf; |
| else return NULL; |
| } |
| |
| char *askfilenamewithdir(const char *title, const char *default_name, const char *dir) |
| { |
| if (*askfilenames(title, default_name, 0, |
| userfilter ? userfilter : filter[0], 0, |
| strbuf, BUFSIZE, dir)) return strbuf; |
| else return NULL; |
| } |
| |
| char *askfilenames(const char *title, const char *default_name, int multi, |
| const char *filters, int filterindex, |
| char *strbuf, int bufsize, |
| const char *dir) |
| { |
| int i; |
| OPENFILENAME ofn; |
| char cwd[MAX_PATH] = ""; |
| HWND prev = GetFocus(); |
| |
| if (!default_name) default_name = ""; |
| strcpy(strbuf, default_name); |
| GetCurrentDirectory(MAX_PATH, cwd); |
| if (!cod[0]) strcpy(cod, cwd); |
| |
| ofn.lStructSize = sizeof(OPENFILENAME); |
| ofn.hwndOwner = current_window ? current_window->handle : 0; |
| ofn.hInstance = 0; |
| ofn.lpstrFilter = filters; |
| ofn.lpstrCustomFilter = NULL; |
| ofn.nMaxCustFilter = 0; |
| ofn.nFilterIndex = filterindex; |
| ofn.lpstrFile = strbuf; |
| ofn.nMaxFile = bufsize; |
| ofn.lpstrFileTitle = NULL; |
| ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT; |
| ofn.lpstrInitialDir = dir ? dir : cod; |
| ofn.lpstrTitle = title; |
| ofn.Flags = OFN_CREATEPROMPT | OFN_HIDEREADONLY | OFN_EXPLORER; |
| if (multi) ofn.Flags |= OFN_ALLOWMULTISELECT; |
| ofn.nFileOffset = 0; |
| ofn.nFileExtension = 0; |
| ofn.lpstrDefExt = "*"; |
| ofn.lCustData = 0L; |
| ofn.lpfnHook = NULL; |
| ofn.lpTemplateName = NULL; |
| |
| if (GetOpenFileName(&ofn) == 0) { |
| if(!dir) GetCurrentDirectory(MAX_PATH, cod); |
| SetCurrentDirectory(cwd); |
| strbuf[0] = 0; |
| strbuf[1] = 0; |
| } else { |
| if(!dir) GetCurrentDirectory(MAX_PATH, cod); |
| SetCurrentDirectory(cwd); |
| for (i = 0; i < 10; i++) if (peekevent()) doevent(); |
| } |
| SetFocus(prev); |
| return strbuf; |
| } |
| |
| wchar_t *askfilenameW(const char *title, const char *default_name) |
| { |
| wchar_t wtitle[1000], wdef_name[MAX_PATH]; |
| |
| mbstowcs(wtitle, title, 1000); |
| if (!default_name) wcscpy(wdef_name, L""); |
| else mbstowcs(wdef_name, default_name, MAX_PATH); |
| if (*askfilenamesW(wtitle, wdef_name, 0, |
| userfilterW ? userfilterW : wfilter[0], 0, |
| NULL)) return wcsbuf; |
| else return NULL; |
| } |
| |
| wchar_t *askfilenamesW(const wchar_t *title, const wchar_t *default_name, |
| int multi, |
| const wchar_t *filters, int filterindex, |
| const wchar_t *dir) |
| { |
| int i; |
| OPENFILENAMEW ofn; |
| char cwd[MAX_PATH]; |
| wchar_t wcod[MAX_PATH]; |
| HWND prev = GetFocus(); |
| |
| if (!default_name) default_name = L""; |
| memset(wcsbuf, 0, sizeof(wcsbuf)); |
| wcscpy(wcsbuf, default_name); |
| GetCurrentDirectory(MAX_PATH, cwd); |
| if (!strcmp(cod, "")) { |
| if (!dir) GetCurrentDirectoryW(MAX_PATH, wcod); else wcscpy(wcod, dir); |
| } else |
| mbstowcs(wcod, cod, MAX_PATH); |
| |
| ofn.lStructSize = sizeof(OPENFILENAME); |
| ofn.hwndOwner = current_window ? current_window->handle : 0; |
| ofn.hInstance = 0; |
| ofn.lpstrFilter = filters; |
| ofn.lpstrCustomFilter = NULL; |
| ofn.nMaxCustFilter = 0; |
| ofn.nFilterIndex = filterindex; |
| ofn.lpstrFile = wcsbuf; |
| ofn.nMaxFile = 65520; /* precaution against overflow */ |
| ofn.lpstrFileTitle = NULL; |
| ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT; |
| ofn.lpstrInitialDir = wcod; |
| ofn.lpstrTitle = title; |
| ofn.Flags = OFN_CREATEPROMPT | OFN_HIDEREADONLY | OFN_EXPLORER; |
| if (multi) ofn.Flags |= OFN_ALLOWMULTISELECT; |
| ofn.nFileOffset = 0; |
| ofn.nFileExtension = 0; |
| ofn.lpstrDefExt = L"*"; |
| ofn.lCustData = 0L; |
| ofn.lpfnHook = NULL; |
| ofn.lpTemplateName = NULL; |
| |
| if (GetOpenFileNameW(&ofn) == 0) { |
| /* This could fail if the Unicode name is not a native name */ |
| DWORD res = GetCurrentDirectory(MAX_PATH, cod); |
| if(res) strcpy(cod, cwd); |
| SetCurrentDirectory(cwd); |
| wcsbuf[0] = 0; |
| wcsbuf[1] = 0; |
| } else { |
| DWORD res = GetCurrentDirectory(MAX_PATH, cod); |
| if(res) strcpy(cod, cwd); |
| SetCurrentDirectory(cwd); |
| for (i = 0; i < 10; i++) if (peekevent()) doevent(); |
| } |
| SetFocus(prev); |
| return wcsbuf; |
| } |
| |
| int countFilenames(const char *list) |
| { |
| const char *temp; |
| int count; |
| count = 0; |
| for (temp = list; *temp; temp += strlen(temp)+1) count++; |
| return count; |
| } |
| |
| char *askfilesave(const char *title, const char *default_name) |
| { |
| return askfilesavewithdir(title, default_name, NULL); |
| } |
| |
| wchar_t *askfilesaveW(const char *title, const char *default_name) |
| { |
| int i; |
| OPENFILENAMEW ofn; |
| wchar_t cwd[MAX_PATH], wdef_name[MAX_PATH], wtitle[1000]; |
| |
| if (!default_name) wcscpy(wdef_name, L""); |
| else mbstowcs(wdef_name, default_name, MAX_PATH); |
| wcscpy(wcsbuf, wdef_name); |
| mbstowcs(wtitle, title, 1000); |
| |
| ofn.lStructSize = sizeof(OPENFILENAME); |
| ofn.hwndOwner = current_window ? current_window->handle : 0; |
| ofn.hInstance = 0; |
| ofn.lpstrFilter = userfilterW ? userfilterW : wfilter[0]; |
| ofn.lpstrCustomFilter = NULL; |
| ofn.nMaxCustFilter = 0; |
| ofn.nFilterIndex = 0; |
| ofn.lpstrFile = wcsbuf; |
| ofn.nMaxFile = BUFSIZE; |
| ofn.lpstrFileTitle = NULL; |
| ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT; |
| if (GetCurrentDirectoryW(MAX_PATH, cwd)) |
| ofn.lpstrInitialDir = cwd; |
| else |
| ofn.lpstrInitialDir = NULL; |
| ofn.lpstrTitle = wtitle; |
| ofn.Flags = OFN_OVERWRITEPROMPT | |
| OFN_NOCHANGEDIR | OFN_HIDEREADONLY; |
| ofn.nFileOffset = 0; |
| ofn.nFileExtension = 0; |
| ofn.lpstrDefExt = NULL; |
| ofn.lCustData = 0L; |
| ofn.lpfnHook = NULL; |
| ofn.lpTemplateName = NULL; |
| |
| if (GetSaveFileNameW(&ofn) == 0) |
| return NULL; |
| else { |
| for (i = 0; i < 10; i++) if (peekevent()) doevent(); |
| return wcsbuf; |
| } |
| } |
| |
| char *askfilesavewithdir(const char *title, const char *default_name, |
| const char *dir) |
| { |
| int i; |
| OPENFILENAME ofn; |
| char cwd[MAX_PATH], *defext = NULL; |
| |
| if (!default_name) default_name = ""; |
| else if(default_name[0] == '|') { |
| defext = (char *)default_name + 2; |
| default_name = ""; |
| } |
| strcpy(strbuf, default_name); |
| |
| ofn.lStructSize = sizeof(OPENFILENAME); |
| ofn.hwndOwner = current_window ? current_window->handle : 0; |
| ofn.hInstance = 0; |
| ofn.lpstrFilter = userfilter?userfilter:filter[0]; |
| ofn.lpstrCustomFilter = NULL; |
| ofn.nMaxCustFilter = 0; |
| ofn.nFilterIndex = 0; |
| ofn.lpstrFile = strbuf; |
| ofn.nMaxFile = BUFSIZE; |
| ofn.lpstrFileTitle = NULL; |
| ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT; |
| if(dir && strlen(dir) > 0) { |
| strcpy(cwd, dir); |
| /* This should have been set to use backslashes in the caller */ |
| ofn.lpstrInitialDir = cwd; |
| } else { |
| if (GetCurrentDirectory(MAX_PATH, cwd)) |
| ofn.lpstrInitialDir = cwd; |
| else |
| ofn.lpstrInitialDir = NULL; |
| } |
| ofn.lpstrTitle = title; |
| ofn.Flags = OFN_OVERWRITEPROMPT | |
| OFN_NOCHANGEDIR | OFN_HIDEREADONLY; |
| ofn.nFileOffset = 0; |
| ofn.nFileExtension = 0; |
| ofn.lpstrDefExt = defext; |
| ofn.lCustData = 0L; |
| ofn.lpfnHook = NULL; |
| ofn.lpTemplateName = NULL; |
| |
| if (GetSaveFileName(&ofn) == 0) |
| return NULL; |
| else { |
| for (i = 0; i < 10; i++) if (peekevent()) doevent(); |
| return strbuf; |
| } |
| } |
| |
| /* |
| * Input a string using a dialog box. |
| */ |
| |
| /* |
| * Dialog information structure: |
| */ |
| #define NOT_CHOSEN_YET -2 |
| |
| typedef struct dialog_data_class { |
| int hit; |
| char * result; |
| label question; |
| field text, pass; |
| button yes, no, cancel; |
| } dialog_data; |
| |
| #define data(w) ((dialog_data *) (getdata(w))) |
| |
| /* |
| * Some strings to use: |
| */ |
| /* static char * OKAY_STRING = "OK"; |
| static char * CANCEL_STRING = "Cancel"; |
| static char * BROWSE_STRING = "Browse"; */ |
| |
| static const char * QUESTION_TITLE = "Question"; |
| static const char * PASSWORD_TITLE = "Password Entry"; |
| |
| static void add_data(window w) |
| { |
| dialog_data *d; |
| |
| d = create (dialog_data); |
| if (! d) |
| return; |
| d->hit = NOT_CHOSEN_YET; |
| |
| setdata(w, d); |
| } |
| |
| static char * get_dialog_string(window w) |
| { |
| dialog_data *d = data(w); |
| |
| if (d->hit < YES) /* cancelled */ |
| return NULL; |
| del_string(d->result); |
| if (d->text) /* question dialog */ |
| d->result = new_string(GA_gettext(d->text)); |
| |
| return d->result; |
| } |
| |
| static void hit_button(control c) |
| { |
| window w = parentwindow(c); |
| dialog_data *d = data(w); |
| int value = getvalue(c); |
| |
| d->hit = value; |
| hide(w); |
| } |
| |
| static void hit_key(window w, int key) |
| { |
| button btn; |
| char *name = NULL; |
| |
| w = parentwindow(w); |
| |
| if (data(w) == NULL) |
| return; |
| |
| if ((btn = data(w)->yes) != NULL) { |
| name = getname(btn); |
| if ((key == '\n') || (tolower(name[0]) == tolower(key))) |
| { |
| flashcontrol(btn); |
| activatecontrol(btn); |
| return; |
| } |
| } |
| |
| if ((btn = data(w)->cancel) != NULL) { |
| name = getname(btn); |
| if ((key == ESC) || (tolower(name[0]) == tolower(key))) |
| { |
| flashcontrol(btn); |
| activatecontrol(btn); |
| return; |
| } |
| } |
| |
| if ((btn = data(w)->no) != NULL) { |
| name = getname(btn); |
| if ((key == ESC) || (tolower(name[0]) == tolower(key))) |
| { |
| flashcontrol(btn); |
| activatecontrol(btn); |
| return; |
| } |
| } |
| |
| } |
| |
| /* |
| * Handle the events from a message dialog, hide the window afterwards. |
| */ |
| static int handle_message_dialog(window w) |
| { |
| window old; |
| dialog_data *d = data(w); |
| |
| old = currentdrawing(); |
| d->hit = NOT_CHOSEN_YET; |
| |
| show(w); |
| while (d->hit == NOT_CHOSEN_YET) { |
| waitevent(); |
| doevent(); |
| } |
| hide(w); |
| |
| if (old) drawto(old); |
| |
| return d->hit; |
| } |
| |
| static window init_askstr_dialog(const char *title, const char *question, |
| const char *default_str) |
| { |
| window win; |
| dialog_data *d; |
| int tw, bw, h, middle; |
| |
| if (! question) |
| question= ""; |
| if (! default_str) |
| default_str = ""; |
| |
| tw = strwidth(SystemFont, G_("Cancel")) * 8; |
| h = getheight(SystemFont); |
| |
| if (tw < 150) tw = 150; |
| |
| win = newwindow(title, rect(0,0,tw+30,h*9+12), |
| Titlebar | Centered | Modal); |
| setbackground(win, dialog_bg()); |
| add_data(win); |
| d = data(win); |
| d->question = newlabel(question, rect(10,h,tw+4,h*2+2), |
| AlignLeft); |
| if (title == PASSWORD_TITLE) |
| d->text = newpassword(default_str, rect(10,h*4,tw+4,h*3/2)); |
| else |
| d->text = newfield(default_str, rect(10,h*4,tw+4,h*3/2)); |
| |
| middle = (tw+30)/2; |
| bw = strwidth(SystemFont, G_("Cancel")) * 3/2; |
| |
| d->yes = newbutton(G_("OK"), |
| rect(middle-bw-10, h*7, bw, h+10), hit_button); |
| setvalue(d->yes, YES); |
| |
| d->cancel = newbutton(G_("Cancel"), |
| rect(middle+10, h*7, bw, h+10), hit_button); |
| setvalue(d->cancel, CANCEL); |
| |
| setkeydown(win, hit_key); |
| |
| return win; |
| } |
| |
| char *askstring(const char *question, const char *default_str) |
| { |
| static window win = NULL; |
| window prev = current_window; |
| |
| if (! win) |
| win = init_askstr_dialog(QUESTION_TITLE, question, default_str); |
| else { |
| settext(data(win)->question, question); |
| settext(data(win)->text, default_str); |
| } |
| if (TopmostDialogs & MB_TOPMOST) |
| BringToTop(win, 1); |
| handle_message_dialog(win); |
| current_window = prev; |
| |
| return get_dialog_string(win); |
| } |
| |
| char *askcdstring(const char *question, const char *default_str) |
| { |
| LPMALLOC g_pMalloc; |
| BROWSEINFO bi; |
| LPITEMIDLIST pidlBrowse; |
| browserInfo info; |
| OSVERSIONINFOEX osvi; |
| |
| strncpy(info.question, question, 40 - 1); |
| info.question[40 - 1] = '\0'; |
| strncpy(info.default_str, default_str, MAX_PATH - 1); |
| info.default_str[MAX_PATH - 1] = '\0'; |
| |
| /* Get the shell's allocator. */ |
| if (!SUCCEEDED(SHGetMalloc(&g_pMalloc))) return NULL; |
| |
| osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); |
| GetVersionEx((OSVERSIONINFO *)&osvi); |
| |
| ZeroMemory(&bi, sizeof(bi)); |
| bi.hwndOwner = 0; |
| if(osvi.dwMajorVersion >= 6) { /* future proof */ |
| /* CSIDL_DESKTOP gets mapped to the User's desktop in Vista |
| (a bug). SHGetFolderLocation is Win2k or later */ |
| if (!SUCCEEDED(SHGetFolderLocation(NULL, CSIDL_DRIVES, NULL, 0, |
| (LPITEMIDLIST *) &bi.pidlRoot))) |
| return NULL; |
| } /* else it is 0, which is CSIDL_DESKTOP */ |
| bi.pszDisplayName = strbuf; |
| bi.lpszTitle = question; |
| bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI; |
| bi.lpfn = (BFFCALLBACK) InitBrowseCallbackProc; |
| bi.lParam = (LPARAM) &info; |
| |
| /* Browse for a folder and return its PIDL. */ |
| pidlBrowse = SHBrowseForFolder(&bi); |
| if (pidlBrowse != NULL) { |
| SHGetPathFromIDList(pidlBrowse, strbuf); |
| g_pMalloc->lpVtbl->Free(g_pMalloc, pidlBrowse); |
| if (strbuf[0]) |
| return strbuf; |
| } |
| return NULL; |
| } |
| |
| char *askpassword(const char *question, const char *default_str) |
| { |
| static window win = NULL; |
| window prev = current_window; |
| |
| if (! win) |
| win = init_askstr_dialog(PASSWORD_TITLE, question, default_str); |
| else { |
| settext(data(win)->question, question); |
| settext(data(win)->text, default_str); |
| } |
| if (TopmostDialogs & MB_TOPMOST) |
| BringToTop(win, 1); |
| handle_message_dialog(win); |
| current_window = prev; |
| |
| return get_dialog_string(win); |
| } |
| |
| char *askUserPass(const char *title) |
| { |
| static window win = NULL; |
| dialog_data *d; |
| window prev = current_window; |
| |
| if (! win) { |
| int tw, bw, h, middle; |
| |
| tw = strwidth(SystemFont, G_("Cancel")) * 8; |
| h = getheight(SystemFont); |
| if (tw < 150) tw = 150; |
| win = newwindow(title, rect(0, 0, tw+30, h*9+12), |
| Titlebar | Centered | Modal); |
| setbackground(win, dialog_bg()); |
| add_data(win); |
| d = data(win); |
| d->question = newlabel(G_("User"), rect(10, h, tw+4, h*2+2), AlignLeft); |
| bw = strwidth(SystemFont, G_("Password")); |
| d->text = newfield("", rect(20+bw, h, tw-6-bw, h*3/2)); |
| newlabel(_("Password"), rect(10, h*4, tw+4, h*2+2), AlignLeft); |
| d->pass = newpassword("", rect(20+bw, h*4, tw-6-bw, h*3/2)); |
| middle = (tw+30)/2; |
| bw = strwidth(SystemFont, G_("Cancel")) * 3/2; |
| |
| d->yes = newbutton(G_("OK"), |
| rect(middle-bw-10, h*7, bw, h+10), hit_button); |
| setvalue(d->yes, YES); |
| |
| d->cancel = newbutton(G_("Cancel"), |
| rect(middle+10, h*7, bw, h+10), hit_button); |
| setvalue(d->cancel, CANCEL); |
| |
| setkeydown(win, hit_key); |
| } else { |
| d = data(win); |
| settext(d->text, ""); |
| settext(d->pass, ""); |
| } |
| if (TopmostDialogs & MB_TOPMOST) |
| BringToTop(win, 1); |
| handle_message_dialog(win); |
| current_window = prev; |
| { |
| char *user, *pass; |
| static char buf[1000]; |
| if (d->hit < YES) /* cancelled */ return ""; |
| if (d->text) user = new_string(GA_gettext(d->text)); |
| else return ""; |
| if (d->pass) pass = new_string(GA_gettext(d->pass)); |
| else return ""; |
| snprintf(buf, 1000, "%s:%s", user, pass); |
| return buf; |
| } |
| return ""; /* -Wall */ |
| } |
| |
| int modeless_active() |
| { |
| if (hModelessDlg) |
| return 1; |
| return 0; |
| } |
| |
| PROTECTED |
| HWND get_modeless() |
| { |
| return hModelessDlg; |
| } |
| |
| void finddialog(textbox t) |
| { |
| static FINDREPLACE fr; |
| static char szFindWhat[80]; |
| |
| fr.lStructSize = sizeof(fr); |
| fr.hwndOwner = t->handle; |
| fr.lpstrFindWhat = szFindWhat; |
| fr.wFindWhatLen = 80; |
| fr.Flags = FR_DOWN; |
| fr.lCustData = 0 ; |
| fr.lpfnHook = NULL ; |
| fr.lpTemplateName = NULL ; |
| |
| hModelessDlg = FindText(&fr); |
| } |
| |
| void replacedialog(textbox t) |
| { |
| static FINDREPLACE fr; |
| static char szFindWhat[80]; |
| static char szReplaceWith[80]; |
| |
| fr.lStructSize = sizeof(fr); |
| fr.hwndOwner = t->handle; |
| fr.lpstrFindWhat = szFindWhat; |
| fr.lpstrReplaceWith = szReplaceWith; |
| fr.wFindWhatLen = 80; |
| fr.wReplaceWithLen = 80; |
| fr.Flags = FR_DOWN; |
| fr.lCustData = 0 ; |
| fr.lpfnHook = NULL ; |
| fr.lpTemplateName = NULL ; |
| |
| hModelessDlg = ReplaceText(&fr); |
| } |
| |
| |
| #include <richedit.h> |
| /* Find and select a string in a rich edit control */ |
| |
| static int richeditfind(HWND hwnd, char *what, int matchcase, |
| int wholeword, int down) |
| { |
| long start, end; |
| CHARRANGE sel; |
| WPARAM w = 0; |
| FINDTEXTEX ft; |
| sendmessage (hwnd, EM_EXGETSEL, 0, &sel) ; |
| start = sel.cpMin; |
| end = sel.cpMax; |
| ft.lpstrText = what; |
| ft.chrgText.cpMin = start; |
| ft.chrgText.cpMax = end; |
| if (down) { |
| w = w | FR_DOWN; |
| ft.chrg.cpMin = end; |
| ft.chrg.cpMax = -1; |
| } |
| else { |
| ft.chrg.cpMin = start; |
| ft.chrg.cpMax = 0; |
| } |
| if (matchcase) w = w | FR_MATCHCASE; |
| if (wholeword) w = w | FR_WHOLEWORD; |
| if (sendmessage(hwnd, EM_FINDTEXTEX, w, &ft) == -1) |
| return 0; |
| else { |
| sendmessage (hwnd, EM_EXSETSEL, 0, &(ft.chrgText)); |
| sendmessage (hwnd, EM_SCROLLCARET, 0, 0) ; |
| } |
| return 1; |
| } |
| |
| static int richeditreplace(HWND hwnd, char *what, char *replacewith, |
| int matchcase, int wholeword, int down) |
| { |
| /* If current selection is the find string, replace it and find next */ |
| long start, end; |
| CHARRANGE sel; |
| char *buf; |
| textbox t = find_by_handle(hwnd); |
| if (t) { |
| sendmessage (hwnd, EM_EXGETSEL, 0, &sel) ; |
| start = sel.cpMin; |
| end = sel.cpMax; |
| if (start < end) { |
| buf = (char *) malloc(end - start + 1); |
| sendmessage(hwnd, EM_GETSELTEXT, 0, buf); |
| if (!strcmp(buf, what)) { |
| checklimittext(t, strlen(replacewith) - strlen(what) + 2); |
| sendmessage (hwnd, EM_REPLACESEL, 1, replacewith); |
| } |
| free(buf); |
| } |
| /* else just find next */ |
| if (richeditfind(hwnd, what, matchcase, wholeword, down)) |
| return 1; |
| } |
| return 0; |
| } |
| |
| PROTECTED |
| void handle_findreplace(HWND hwnd, LPFINDREPLACE pfr) |
| { |
| CHARRANGE sel; |
| int matchcase=0, wholeword=0, down=0; |
| char buf[100]; |
| if (pfr->Flags & FR_MATCHCASE) matchcase = 1; |
| if (pfr->Flags & FR_WHOLEWORD) wholeword = 1; |
| if (pfr->Flags & FR_DOWN) down = 1; |
| |
| if (pfr->Flags & FR_FINDNEXT) { |
| if (!richeditfind(hwnd, pfr->lpstrFindWhat, matchcase, wholeword, down)) { |
| snprintf(buf, 100, G_("\"%s\" not found"), pfr->lpstrFindWhat); |
| askok(buf); |
| } |
| } |
| else if (pfr->Flags & FR_REPLACE) { |
| if (!richeditreplace(hwnd, pfr->lpstrFindWhat, pfr->lpstrReplaceWith, matchcase, wholeword, down)) { |
| snprintf(buf, 100, G_("\"%s\" not found"), pfr->lpstrFindWhat); |
| askok(buf); |
| } |
| } |
| else if (pfr->Flags & FR_REPLACEALL) { |
| /* replace all in the whole buffer then return to original selection state */ |
| sendmessage (hwnd, EM_EXGETSEL, 0, &sel) ; |
| sendmessage (hwnd, EM_SETSEL, 0, 0) ; |
| while ( richeditreplace(hwnd, pfr->lpstrFindWhat, pfr->lpstrReplaceWith, matchcase, wholeword, down) ) ; |
| sendmessage (hwnd, EM_EXSETSEL, 0, &sel) ; |
| } |
| |
| else if (pfr->Flags & FR_DIALOGTERM) |
| hModelessDlg = NULL; |
| } |