X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fdialog-msw.c;h=0ddcc6a7dda2413aa2cee3d5097d71b99a0c7e0c;hb=eb38249f0761537cb618c7ca1c523a32353a3583;hp=b9234e35bc6c8b84403181abf6b61a8b5bf5b177;hpb=02f4d2761a98c5cb9d5b423d2361160a5d8c9ee4;p=chise%2Fxemacs-chise.git.1 diff --git a/src/dialog-msw.c b/src/dialog-msw.c index b9234e3..0ddcc6a 100644 --- a/src/dialog-msw.c +++ b/src/dialog-msw.c @@ -42,7 +42,9 @@ Lisp_Object Qdialog_box_error; static Lisp_Object Q_initial_directory; static Lisp_Object Q_initial_filename; static Lisp_Object Q_filter_list; +/* Declared in general-slots.h static Lisp_Object Q_title; +*/ static Lisp_Object Q_allow_multi_select; static Lisp_Object Q_create_prompt_on_nonexistent; static Lisp_Object Q_overwrite_prompt; @@ -285,6 +287,14 @@ free_dynarr_opaque_ptr (Lisp_Object arg) return arg; } +/* Unwind protection decrements dialog count */ +static Lisp_Object +dialog_popped_down (Lisp_Object arg) +{ + popup_up_p--; + return Qnil; +} + #define ALIGN_TEMPLATE \ { \ @@ -332,14 +342,133 @@ static struct { 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; @@ -673,14 +802,21 @@ static Lisp_Object mswindows_make_dialog_box_internal (struct frame* f, Lisp_Object type, Lisp_Object keys) { + int unbind_count = specpdl_depth (); + record_unwind_protect (dialog_popped_down, Qnil); + popup_up_p++; + if (EQ (type, Qfile)) - return handle_file_dialog_box (f, keys); + return unbind_to (unbind_count, handle_file_dialog_box (f, keys)); + else if (EQ (type, Qdirectory)) + return unbind_to (unbind_count, handle_directory_dialog_box (f, keys)); else if (EQ (type, Qquestion)) - return handle_question_dialog_box (f, keys); + return unbind_to (unbind_count, handle_question_dialog_box (f, keys)); else if (EQ (type, Qprint)) - return mswindows_handle_print_dialog_box (f, keys); + return unbind_to (unbind_count, mswindows_handle_print_dialog_box (f, keys)); else if (EQ (type, Qpage_setup)) - return mswindows_handle_page_setup_dialog_box (f, keys); + return unbind_to (unbind_count, + mswindows_handle_page_setup_dialog_box (f, keys)); else signal_type_error (Qunimplemented, "Dialog box type", type); return Qnil;