+static struct
+{
+ int errmess;
+ char *errname;
+} common_dialog_errors[] =
+{
+ { CDERR_DIALOGFAILURE, "CDERR_DIALOGFAILURE" },
+ { CDERR_FINDRESFAILURE, "CDERR_FINDRESFAILURE" },
+ { CDERR_INITIALIZATION, "CDERR_INITIALIZATION" },
+ { CDERR_LOADRESFAILURE, "CDERR_LOADRESFAILURE" },
+ { CDERR_LOADSTRFAILURE, "CDERR_LOADSTRFAILURE" },
+ { CDERR_LOCKRESFAILURE, "CDERR_LOCKRESFAILURE" },
+ { CDERR_MEMALLOCFAILURE, "CDERR_MEMALLOCFAILURE" },
+ { CDERR_MEMLOCKFAILURE, "CDERR_MEMLOCKFAILURE" },
+ { CDERR_NOHINSTANCE, "CDERR_NOHINSTANCE" },
+ { CDERR_NOHOOK, "CDERR_NOHOOK" },
+ { CDERR_NOTEMPLATE, "CDERR_NOTEMPLATE" },
+ { CDERR_REGISTERMSGFAIL, "CDERR_REGISTERMSGFAIL" },
+ { CDERR_STRUCTSIZE, "CDERR_STRUCTSIZE" },
+ { PDERR_CREATEICFAILURE, "PDERR_CREATEICFAILURE" },
+ { PDERR_DEFAULTDIFFERENT, "PDERR_DEFAULTDIFFERENT" },
+ { PDERR_DNDMMISMATCH, "PDERR_DNDMMISMATCH" },
+ { PDERR_GETDEVMODEFAIL, "PDERR_GETDEVMODEFAIL" },
+ { PDERR_INITFAILURE, "PDERR_INITFAILURE" },
+ { PDERR_LOADDRVFAILURE, "PDERR_LOADDRVFAILURE" },
+ { PDERR_NODEFAULTPRN, "PDERR_NODEFAULTPRN" },
+ { PDERR_NODEVICES, "PDERR_NODEVICES" },
+ { PDERR_PARSEFAILURE, "PDERR_PARSEFAILURE" },
+ { PDERR_PRINTERNOTFOUND, "PDERR_PRINTERNOTFOUND" },
+ { PDERR_RETDEFFAILURE, "PDERR_RETDEFFAILURE" },
+ { PDERR_SETUPFAILURE, "PDERR_SETUPFAILURE" },
+ { CFERR_MAXLESSTHANMIN, "CFERR_MAXLESSTHANMIN" },
+ { CFERR_NOFONTS, "CFERR_NOFONTS" },
+ { FNERR_BUFFERTOOSMALL, "FNERR_BUFFERTOOSMALL" },
+ { FNERR_INVALIDFILENAME, "FNERR_INVALIDFILENAME" },
+ { FNERR_SUBCLASSFAILURE, "FNERR_SUBCLASSFAILURE" },
+ { FRERR_BUFFERLENGTHZERO, "FRERR_BUFFERLENGTHZERO" },
+};
+
+struct param_data {
+ char* fname;
+ char* unknown_fname;
+ int validate;
+};
+
+static int
+CALLBACK handle_directory_proc (HWND hwnd, UINT msg,
+ LPARAM lParam, LPARAM lpData)
+{
+ TCHAR szDir[MAX_PATH];
+ struct param_data* pd = (struct param_data*)lpData;
+
+ switch(msg) {
+ case BFFM_INITIALIZED:
+ // WParam is TRUE since you are passing a path.
+ // It would be FALSE if you were passing a pidl.
+ SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)pd->fname);
+ break;
+
+ case BFFM_SELCHANGED:
+ // Set the status window to the currently selected path.
+ if (SHGetPathFromIDList((LPITEMIDLIST) lParam, szDir)) {
+ SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)szDir);
+ }
+ break;
+
+ case BFFM_VALIDATEFAILED:
+ if (pd->validate)
+ return TRUE;
+ else
+ pd->unknown_fname = xstrdup((char*)lParam);
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+static Lisp_Object
+handle_directory_dialog_box (struct frame *f, Lisp_Object keys)
+{
+ Lisp_Object ret = Qnil;
+ BROWSEINFO bi;
+ LPITEMIDLIST pidl;
+ LPMALLOC pMalloc;
+ struct param_data pd;
+
+ xzero(pd);
+ xzero(bi);
+
+ bi.lParam = (LPARAM)&pd;
+ bi.hwndOwner = FRAME_MSWINDOWS_HANDLE (f);
+ bi.pszDisplayName = 0;
+ bi.pidlRoot = 0;
+ bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_EDITBOX;
+ bi.lpfn = handle_directory_proc;
+
+ LOCAL_FILE_FORMAT_TO_TSTR (Fexpand_file_name (build_string (""), Qnil),
+ pd.fname);
+
+ {
+ EXTERNAL_PROPERTY_LIST_LOOP_3 (key, value, keys)
+ {
+ if (EQ (key, Q_title))
+ {
+ CHECK_STRING (value);
+ LISP_STRING_TO_EXTERNAL (value, bi.lpszTitle, Qmswindows_tstr);
+ }
+ else if (EQ (key, Q_initial_directory))
+ LOCAL_FILE_FORMAT_TO_TSTR (Fexpand_file_name (value, Qnil),
+ pd.fname);
+ else if (EQ (key, Q_initial_filename))
+ ; /* do nothing */
+ else if (EQ (key, Q_file_must_exist))
+ {
+ if (!NILP (value)) {
+ pd.validate = TRUE;
+ bi.ulFlags |= BIF_VALIDATE;
+ }
+ else
+ bi.ulFlags &= ~BIF_VALIDATE;
+ }
+ else
+ syntax_error ("Unrecognized directory dialog keyword", key);
+ }
+ }
+
+ if (SHGetMalloc(&pMalloc) == NOERROR)
+ {
+ pidl = SHBrowseForFolder(&bi);
+ if (pidl) {
+ TCHAR* szDir = alloca (MAX_PATH);
+
+ if (SHGetPathFromIDList(pidl, szDir)) {
+ ret = tstr_to_local_file_format (szDir);
+ }
+
+ pMalloc->lpVtbl->Free(pMalloc, pidl);
+ pMalloc->lpVtbl->Release(pMalloc);
+ return ret;
+ }
+ else if (pd.unknown_fname != 0) {
+ ret = tstr_to_local_file_format (pd.unknown_fname);
+ xfree(pd.unknown_fname);
+ }
+ else while (1)
+ signal_quit ();
+ }
+ else
+ signal_type_error (Qdialog_box_error,
+ "Unable to create folder browser",
+ make_int (0));
+ return ret;
+}
+
+static Lisp_Object
+handle_file_dialog_box (struct frame *f, Lisp_Object keys)
+{
+ OPENFILENAME ofn;
+
+ char fnbuf[8000];
+
+ xzero (ofn);
+ ofn.lStructSize = sizeof (ofn);
+ ofn.Flags = OFN_EXPLORER;
+ ofn.hwndOwner = FRAME_MSWINDOWS_HANDLE (f);
+ ofn.lpstrFile = fnbuf;
+ ofn.nMaxFile = sizeof (fnbuf) / XETCHAR_SIZE;
+ xetcscpy (fnbuf, XETEXT (""));
+
+ LOCAL_FILE_FORMAT_TO_TSTR (Fexpand_file_name (build_string (""), Qnil),
+ ofn.lpstrInitialDir);
+
+ {
+ EXTERNAL_PROPERTY_LIST_LOOP_3 (key, value, keys)
+ {
+ if (EQ (key, Q_initial_filename))
+ {
+ Extbyte *fnout;
+
+ CHECK_STRING (value);
+ LOCAL_FILE_FORMAT_TO_TSTR (value, fnout);
+ xetcscpy (fnbuf, fnout);
+ }
+ else if (EQ (key, Q_title))
+ {
+ CHECK_STRING (value);
+ LISP_STRING_TO_EXTERNAL (value, ofn.lpstrTitle, Qmswindows_tstr);
+ }
+ else if (EQ (key, Q_initial_directory))
+ LOCAL_FILE_FORMAT_TO_TSTR (Fexpand_file_name (value, Qnil),
+ ofn.lpstrInitialDir);
+ else if (EQ (key, Q_file_must_exist))
+ {
+ if (!NILP (value))
+ ofn.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
+ else
+ ofn.Flags &= ~(OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST);
+ }
+ else
+ syntax_error ("Unrecognized file-dialog keyword", key);
+ }
+ }
+
+ if (!GetOpenFileName (&ofn))
+ {
+ DWORD err = CommDlgExtendedError ();
+ if (!err)
+ {
+ while (1)
+ signal_quit ();
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < countof (common_dialog_errors); i++)
+ {
+ if (common_dialog_errors[i].errmess == err)
+ signal_type_error (Qdialog_box_error,
+ "Creating file-dialog-box",
+ build_string
+ (common_dialog_errors[i].errname));
+ }
+
+ signal_type_error (Qdialog_box_error,
+ "Unknown common dialog box error???",
+ make_int (err));
+ }
+ }
+
+ return tstr_to_local_file_format (ofn.lpstrFile);
+}
+
+static Lisp_Object
+handle_question_dialog_box (struct frame *f, Lisp_Object keys)