comparison src/dialog-msw.c @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children 576fb035e263
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
1 /* Implements elisp-programmable dialog boxes -- MS Windows interface. 1 /* Implements elisp-programmable dialog boxes -- MS Windows interface.
2 Copyright (C) 1998 Kirill M. Katsnelson <kkm@kis.ru> 2 Copyright (C) 1998 Kirill M. Katsnelson <kkm@kis.ru>
3 Copyright (C) 2000 Ben Wing.
3 4
4 This file is part of XEmacs. 5 This file is part of XEmacs.
5 6
6 XEmacs is free software; you can redistribute it and/or modify it 7 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the 8 under the terms of the GNU General Public License as published by the
31 #include "console-msw.h" 32 #include "console-msw.h"
32 #include "frame.h" 33 #include "frame.h"
33 #include "gui.h" 34 #include "gui.h"
34 #include "opaque.h" 35 #include "opaque.h"
35 36
37 #include <cderr.h>
38 #include <commdlg.h>
39
40 Lisp_Object Qdialog_box_error;
41
42 static Lisp_Object Q_initial_directory;
43 static Lisp_Object Q_initial_filename;
44 static Lisp_Object Q_filter_list;
45 static Lisp_Object Q_title;
46 static Lisp_Object Q_allow_multi_select;
47 static Lisp_Object Q_create_prompt_on_nonexistent;
48 static Lisp_Object Q_overwrite_prompt;
49 static Lisp_Object Q_file_must_exist;
50 static Lisp_Object Q_no_network_button;
51 static Lisp_Object Q_no_read_only_return;
52
36 /* List containing all dialog data structures of currently popped up 53 /* List containing all dialog data structures of currently popped up
37 dialogs. Each item is a cons of frame object and a vector of 54 dialogs. */
38 callbacks for buttons in the dialog, in order */
39 static Lisp_Object Vdialog_data_list; 55 static Lisp_Object Vdialog_data_list;
56
57 /* List of popup frames wanting keyboard traversal handled */
58 static Lisp_Object Vpopup_frame_list;
59
60 Lisp_Object Vdefault_file_dialog_filter_alist;
40 61
41 /* DLUs per character metrics */ 62 /* DLUs per character metrics */
42 #define X_DLU_PER_CHAR 4 63 #define X_DLU_PER_CHAR 4
43 #define Y_DLU_PER_CHAR 8 64 #define Y_DLU_PER_CHAR 8
44 65
107 latter is centered across the dialog, by giving it extra edge 128 latter is centered across the dialog, by giving it extra edge
108 margins. Otherwise, minimal margins are given to the button row. 129 margins. Otherwise, minimal margins are given to the button row.
109 */ 130 */
110 131
111 #define ID_ITEM_BIAS 32 132 #define ID_ITEM_BIAS 32
133
134 void
135 mswindows_register_popup_frame (Lisp_Object frame)
136 {
137 Vpopup_frame_list = Fcons (frame, Vpopup_frame_list);
138 }
139
140 void
141 mswindows_unregister_popup_frame (Lisp_Object frame)
142 {
143 Vpopup_frame_list = delq_no_quit (frame, Vpopup_frame_list);
144 }
145
146 /* Dispatch message to any dialog boxes. Return non-zero if dispatched. */
147 int
148 mswindows_is_dialog_msg (MSG *msg)
149 {
150 LIST_LOOP_2 (data, Vdialog_data_list)
151 {
152 if (IsDialogMessage (XMSWINDOWS_DIALOG_ID (data)->hwnd, msg))
153 return 1;
154 }
155
156 {
157 LIST_LOOP_2 (popup, Vpopup_frame_list)
158 {
159 HWND hwnd = FRAME_MSWINDOWS_HANDLE (XFRAME (popup));
160 if (IsDialogMessage (hwnd, msg))
161 return 1;
162 }
163 }
164 return 0;
165 }
166
167 static Lisp_Object
168 mark_mswindows_dialog_id (Lisp_Object obj)
169 {
170 struct mswindows_dialog_id *data = XMSWINDOWS_DIALOG_ID (obj);
171 mark_object (data->frame);
172 return data->callbacks;
173 }
174
175 DEFINE_LRECORD_IMPLEMENTATION ("mswindows-dialog-id", mswindows_dialog_id,
176 mark_mswindows_dialog_id, 0, 0, 0, 0, 0,
177 struct mswindows_dialog_id);
112 178
113 /* Dialog procedure */ 179 /* Dialog procedure */
114 static BOOL CALLBACK 180 static BOOL CALLBACK
115 dialog_proc (HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param) 181 dialog_proc (HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
116 { 182 {
129 break; 195 break;
130 196
131 case WM_COMMAND: 197 case WM_COMMAND:
132 { 198 {
133 Lisp_Object fn, arg, data; 199 Lisp_Object fn, arg, data;
200 struct mswindows_dialog_id *did;
201
134 VOID_TO_LISP (data, GetWindowLong (hwnd, DWL_USER)); 202 VOID_TO_LISP (data, GetWindowLong (hwnd, DWL_USER));
135 203 did = XMSWINDOWS_DIALOG_ID (data);
136 assert (w_param >= ID_ITEM_BIAS 204 if (w_param != IDCANCEL) /* user pressed escape */
137 && w_param < XVECTOR_LENGTH (XCDR (data)) + ID_ITEM_BIAS); 205 {
138 206 assert (w_param >= ID_ITEM_BIAS
139 get_gui_callback (XVECTOR_DATA (XCDR (data)) [w_param - ID_ITEM_BIAS], 207 && w_param
140 &fn, &arg); 208 < XVECTOR_LENGTH (did->callbacks) + ID_ITEM_BIAS);
141 mswindows_enqueue_misc_user_event (XCAR (data), fn, arg); 209
210 get_gui_callback (XVECTOR_DATA (did->callbacks)
211 [w_param - ID_ITEM_BIAS],
212 &fn, &arg);
213 mswindows_enqueue_misc_user_event (did->frame, fn, arg);
214 }
215 else
216 mswindows_enqueue_misc_user_event (did->frame, Qrun_hooks,
217 Qmenu_no_selection_hook);
218 /* #### need to error-protect! will do so when i merge in
219 my working ws */
220 va_run_hook_with_args (Qdelete_dialog_box_hook, 1, data);
142 221
143 DestroyWindow (hwnd); 222 DestroyWindow (hwnd);
144 } 223 }
145 break; 224 break;
146 225
166 length = MultiByteToWideChar (CP_ACP, 0, mbcs_string, -1, 245 length = MultiByteToWideChar (CP_ACP, 0, mbcs_string, -1,
167 uni_string, sizeof(WCHAR) * (length + 1)); 246 uni_string, sizeof(WCHAR) * (length + 1));
168 Dynarr_add_many (dynarr, uni_string, sizeof(WCHAR) * length); 247 Dynarr_add_many (dynarr, uni_string, sizeof(WCHAR) * length);
169 } 248 }
170 249
250 /* Helper function which converts the supplied string STRING into Unicode and
251 pushes it at the end of DYNARR */
252 static void
253 push_bufbyte_string_as_unicode (unsigned_char_dynarr* dynarr, Bufbyte *string,
254 Bytecount len)
255 {
256 Extbyte *mbcs_string;
257 Charcount length = bytecount_to_charcount (string, len);
258 LPWSTR uni_string;
259
260 TO_EXTERNAL_FORMAT (C_STRING, string,
261 C_STRING_ALLOCA, mbcs_string,
262 Qnative);
263 uni_string = alloca_array (WCHAR, length + 1);
264 length = MultiByteToWideChar (CP_ACP, 0, mbcs_string, -1,
265 uni_string, sizeof(WCHAR) * (length + 1));
266 Dynarr_add_many (dynarr, uni_string, sizeof(WCHAR) * length);
267 }
268
171 /* Given button TEXT, return button width in DLU */ 269 /* Given button TEXT, return button width in DLU */
172 static unsigned int 270 static unsigned int
173 button_width (Lisp_Object text) 271 button_width (Lisp_Object text)
174 { 272 {
175 unsigned int width = X_DLU_PER_CHAR * XSTRING_CHAR_LENGTH (text); 273 unsigned int width = X_DLU_PER_CHAR * XSTRING_CHAR_LENGTH (text);
190 unsigned int slippage = Dynarr_length (template) & 3; \ 288 unsigned int slippage = Dynarr_length (template) & 3; \
191 if (slippage) \ 289 if (slippage) \
192 Dynarr_add_many (template, &zeroes, slippage); \ 290 Dynarr_add_many (template, &zeroes, slippage); \
193 } 291 }
194 292
195 static void 293 static struct
196 mswindows_popup_dialog_box (struct frame* f, Lisp_Object desc) 294 {
295 int errmess;
296 char *errname;
297 } common_dialog_errors[] =
298 {
299 { CDERR_DIALOGFAILURE, "CDERR_DIALOGFAILURE" },
300 { CDERR_FINDRESFAILURE, "CDERR_FINDRESFAILURE" },
301 { CDERR_INITIALIZATION, "CDERR_INITIALIZATION" },
302 { CDERR_LOADRESFAILURE, "CDERR_LOADRESFAILURE" },
303 { CDERR_LOADSTRFAILURE, "CDERR_LOADSTRFAILURE" },
304 { CDERR_LOCKRESFAILURE, "CDERR_LOCKRESFAILURE" },
305 { CDERR_MEMALLOCFAILURE, "CDERR_MEMALLOCFAILURE" },
306 { CDERR_MEMLOCKFAILURE, "CDERR_MEMLOCKFAILURE" },
307 { CDERR_NOHINSTANCE, "CDERR_NOHINSTANCE" },
308 { CDERR_NOHOOK, "CDERR_NOHOOK" },
309 { CDERR_NOTEMPLATE, "CDERR_NOTEMPLATE" },
310 { CDERR_REGISTERMSGFAIL, "CDERR_REGISTERMSGFAIL" },
311 { CDERR_STRUCTSIZE, "CDERR_STRUCTSIZE" },
312 { PDERR_CREATEICFAILURE, "PDERR_CREATEICFAILURE" },
313 { PDERR_DEFAULTDIFFERENT, "PDERR_DEFAULTDIFFERENT" },
314 { PDERR_DNDMMISMATCH, "PDERR_DNDMMISMATCH" },
315 { PDERR_GETDEVMODEFAIL, "PDERR_GETDEVMODEFAIL" },
316 { PDERR_INITFAILURE, "PDERR_INITFAILURE" },
317 { PDERR_LOADDRVFAILURE, "PDERR_LOADDRVFAILURE" },
318 { PDERR_NODEFAULTPRN, "PDERR_NODEFAULTPRN" },
319 { PDERR_NODEVICES, "PDERR_NODEVICES" },
320 { PDERR_PARSEFAILURE, "PDERR_PARSEFAILURE" },
321 { PDERR_PRINTERNOTFOUND, "PDERR_PRINTERNOTFOUND" },
322 { PDERR_RETDEFFAILURE, "PDERR_RETDEFFAILURE" },
323 { PDERR_SETUPFAILURE, "PDERR_SETUPFAILURE" },
324 { CFERR_MAXLESSTHANMIN, "CFERR_MAXLESSTHANMIN" },
325 { CFERR_NOFONTS, "CFERR_NOFONTS" },
326 { FNERR_BUFFERTOOSMALL, "FNERR_BUFFERTOOSMALL" },
327 { FNERR_INVALIDFILENAME, "FNERR_INVALIDFILENAME" },
328 { FNERR_SUBCLASSFAILURE, "FNERR_SUBCLASSFAILURE" },
329 { FRERR_BUFFERLENGTHZERO, "FRERR_BUFFERLENGTHZERO" },
330 };
331
332 static Lisp_Object
333 handle_file_dialog_box (struct frame *f, Lisp_Object keys)
334 {
335 OPENFILENAME ofn;
336 char fnbuf[8000];
337
338 xzero (ofn);
339 ofn.lStructSize = sizeof (ofn);
340 ofn.hwndOwner = FRAME_MSWINDOWS_HANDLE (f);
341 ofn.lpstrFile = fnbuf;
342 ofn.nMaxFile = sizeof (fnbuf) / XETCHAR_SIZE;
343 xetcscpy (fnbuf, XETEXT (""));
344
345 LOCAL_FILE_FORMAT_TO_TSTR (Fexpand_file_name (build_string (""), Qnil),
346 ofn.lpstrInitialDir);
347
348 {
349 EXTERNAL_PROPERTY_LIST_LOOP_3 (key, value, keys)
350 {
351 if (EQ (key, Q_initial_filename))
352 {
353 Extbyte *fnout;
354
355 CHECK_STRING (value);
356 LOCAL_FILE_FORMAT_TO_TSTR (value, fnout);
357 xetcscpy (fnbuf, fnout);
358 }
359 else if (EQ (key, Q_title))
360 {
361 CHECK_STRING (value);
362 LISP_STRING_TO_EXTERNAL (value, ofn.lpstrTitle, Qmswindows_tstr);
363 }
364 else if (EQ (key, Q_initial_directory))
365 LOCAL_FILE_FORMAT_TO_TSTR (Fexpand_file_name (value, Qnil),
366 ofn.lpstrInitialDir);
367 else if (EQ (key, Q_file_must_exist))
368 {
369 if (!NILP (value))
370 ofn.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
371 else
372 ofn.Flags &= ~(OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST);
373 }
374 else
375 syntax_error ("Unrecognized file-dialog keyword", key);
376 }
377 }
378
379 if (!GetOpenFileName (&ofn))
380 {
381 DWORD err = CommDlgExtendedError ();
382 if (!err)
383 {
384 while (1)
385 signal_quit ();
386 }
387 else
388 {
389 int i;
390
391 for (i = 0; i < countof (common_dialog_errors); i++)
392 {
393 if (common_dialog_errors[i].errmess == err)
394 signal_type_error (Qdialog_box_error,
395 "Creating file-dialog-box",
396 build_string
397 (common_dialog_errors[i].errname));
398 }
399
400 signal_type_error (Qdialog_box_error,
401 "Unknown common dialog box error???",
402 make_int (err));
403 }
404 }
405
406 return tstr_to_local_file_format (ofn.lpstrFile);
407 }
408
409 static Lisp_Object
410 handle_question_dialog_box (struct frame *f, Lisp_Object keys)
197 { 411 {
198 Lisp_Object_dynarr *dialog_items = Dynarr_new (Lisp_Object); 412 Lisp_Object_dynarr *dialog_items = Dynarr_new (Lisp_Object);
199 unsigned_char_dynarr *template = Dynarr_new (unsigned_char); 413 unsigned_char_dynarr *template = Dynarr_new (unsigned_char);
200 unsigned int button_row_width = 0; 414 unsigned int button_row_width = 0;
201 unsigned int text_width, text_height; 415 unsigned int text_width, text_height;
416 Lisp_Object question = Qnil, title = Qnil;
202 417
203 int unbind_count = specpdl_depth (); 418 int unbind_count = specpdl_depth ();
204 record_unwind_protect (free_dynarr_opaque_ptr, 419 record_unwind_protect (free_dynarr_opaque_ptr,
205 make_opaque_ptr (dialog_items)); 420 make_opaque_ptr (dialog_items));
206 record_unwind_protect (free_dynarr_opaque_ptr, 421 record_unwind_protect (free_dynarr_opaque_ptr,
207 make_opaque_ptr (template)); 422 make_opaque_ptr (template));
208 423
209 /* A big NO NEED to GCPRO gui_items stored in the array: they are just 424 /* A big NO NEED to GCPRO gui_items stored in the array: they are just
210 pointers into DESC list, which is GC-protected by the caller */ 425 pointers into KEYS list, which is GC-protected by the caller */
211 426
212 /* Parse each item in the dialog into gui_item structs, and stuff a dynarr
213 of these. Calculate button row width in this loop too */
214 { 427 {
215 Lisp_Object item_cons; 428 EXTERNAL_PROPERTY_LIST_LOOP_3 (key, value, keys)
216
217 EXTERNAL_LIST_LOOP (item_cons, XCDR (desc))
218 { 429 {
219 if (!NILP (XCAR (item_cons))) 430 if (EQ (key, Q_question))
220 { 431 {
221 Lisp_Object gitem = gui_parse_item_keywords (XCAR (item_cons)); 432 CHECK_STRING (value);
222 Dynarr_add (dialog_items, gitem); 433 question = value;
223 button_row_width += button_width (XGUI_ITEM (gitem)->name) 434 }
224 + X_BUTTON_MARGIN; 435 else if (EQ (key, Q_title))
225 } 436 {
437 CHECK_STRING (value);
438 title = value;
439 }
440 else if (EQ (key, Q_buttons))
441 {
442 Lisp_Object item_cons;
443
444 /* Parse each item in the dialog into gui_item structs,
445 and stuff a dynarr of these. Calculate button row width
446 in this loop too */
447 EXTERNAL_LIST_LOOP (item_cons, value)
448 {
449 if (!NILP (XCAR (item_cons)))
450 {
451 Lisp_Object gitem =
452 gui_parse_item_keywords (XCAR (item_cons));
453 Dynarr_add (dialog_items, gitem);
454 button_row_width += button_width (XGUI_ITEM (gitem)->name)
455 + X_BUTTON_MARGIN;
456 }
457 }
458
459 button_row_width -= X_BUTTON_MARGIN;
460 }
461 else
462 syntax_error ("Unrecognized question-dialog keyword", key);
226 } 463 }
227 if (Dynarr_length (dialog_items) == 0)
228 signal_simple_error ("Dialog descriptor provides no active items", desc);
229 button_row_width -= X_BUTTON_MARGIN;
230 } 464 }
465
466 if (Dynarr_length (dialog_items) == 0)
467 syntax_error ("Dialog descriptor provides no buttons", keys);
468
469 if (NILP (question))
470 syntax_error ("Dialog descriptor provides no question", keys);
231 471
232 /* Determine the final width layout */ 472 /* Determine the final width layout */
233 { 473 {
234 Bufbyte *p = XSTRING_DATA (XCAR (desc)); 474 Bufbyte *p = XSTRING_DATA (question);
235 Charcount string_max = 0, this_length = 0; 475 Charcount string_max = 0, this_length = 0;
236 while (1) 476 while (1)
237 { 477 {
238 Emchar ch = charptr_emchar (p); 478 Emchar ch = charptr_emchar (p);
239 INC_CHARPTR (p); 479 INC_CHARPTR (p);
259 text_width = max (text_width, button_row_width); 499 text_width = max (text_width, button_row_width);
260 } 500 }
261 501
262 /* Now calculate the height for the text control */ 502 /* Now calculate the height for the text control */
263 { 503 {
264 Bufbyte *p = XSTRING_DATA (XCAR (desc)); 504 Bufbyte *p = XSTRING_DATA (question);
265 Charcount break_at = text_width / X_DLU_PER_CHAR; 505 Charcount break_at = text_width / X_DLU_PER_CHAR;
266 Charcount char_pos = 0; 506 Charcount char_pos = 0;
267 int num_lines = 1; 507 int num_lines = 1;
268 Emchar ch; 508 Emchar ch;
269 509
270 while ((ch = charptr_emchar (p)) != (Emchar)'\0') 510 while ((ch = charptr_emchar (p)) != (Emchar) '\0')
271 { 511 {
272 INC_CHARPTR (p); 512 INC_CHARPTR (p);
273 char_pos += ch != (Emchar)'\n'; 513 char_pos += ch != (Emchar) '\n';
274 if (ch == (Emchar)'\n' || char_pos == break_at) 514 if (ch == (Emchar) '\n' || char_pos == break_at)
275 { 515 {
276 ++num_lines; 516 ++num_lines;
277 char_pos = 0; 517 char_pos = 0;
278 } 518 }
279 } 519 }
303 Dynarr_add_many (template, &dlg_tem, sizeof (dlg_tem)); 543 Dynarr_add_many (template, &dlg_tem, sizeof (dlg_tem));
304 544
305 /* We want no menu and standard class */ 545 /* We want no menu and standard class */
306 Dynarr_add_many (template, &zeroes, 4); 546 Dynarr_add_many (template, &zeroes, 4);
307 547
308 /* And the third is the dialog title. "XEmacs" as long as we do not supply 548 /* And the third is the dialog title. "XEmacs" unless one is supplied.
309 one in descriptor. Note that the string must be in Unicode. */ 549 Note that the string must be in Unicode. */
310 Dynarr_add_many (template, L"XEmacs", 14); 550 if (NILP (title))
551 Dynarr_add_many (template, L"XEmacs", 14);
552 else
553 push_lisp_string_as_unicode (template, title);
311 554
312 /* We want standard dialog font */ 555 /* We want standard dialog font */
313 Dynarr_add_many (template, L"\x08MS Shell Dlg", 28); 556 Dynarr_add_many (template, L"\x08MS Shell Dlg", 28);
314 557
315 /* Next add text control. */ 558 /* Next add text control. */
327 /* Right after class id follows */ 570 /* Right after class id follows */
328 Dynarr_add_many (template, &ones, 2); 571 Dynarr_add_many (template, &ones, 2);
329 Dynarr_add_many (template, &static_class_id, sizeof (static_class_id)); 572 Dynarr_add_many (template, &static_class_id, sizeof (static_class_id));
330 573
331 /* Next thing to add is control text, as Unicode string */ 574 /* Next thing to add is control text, as Unicode string */
332 push_lisp_string_as_unicode (template, XCAR (desc)); 575 push_lisp_string_as_unicode (template, question);
333 576
334 /* Specify 0 length creation data */ 577 /* Specify 0 length creation data */
335 Dynarr_add_many (template, &zeroes, 2); 578 Dynarr_add_many (template, &zeroes, 2);
336 579
337 /* Now it's the button time */ 580 /* Now it's the button time */
360 /* Right after 0xFFFF and class id atom follows */ 603 /* Right after 0xFFFF and class id atom follows */
361 Dynarr_add_many (template, &ones, 2); 604 Dynarr_add_many (template, &ones, 2);
362 Dynarr_add_many (template, &button_class_id, sizeof (button_class_id)); 605 Dynarr_add_many (template, &button_class_id, sizeof (button_class_id));
363 606
364 /* Next thing to add is control text, as Unicode string */ 607 /* Next thing to add is control text, as Unicode string */
365 push_lisp_string_as_unicode (template, pgui_item->name); 608 {
609 Lisp_Object ctext = pgui_item->name;
610 Emchar accel_unused;
611 Bufbyte *trans = (Bufbyte *) alloca (2 * XSTRING_LENGTH (ctext) + 3);
612 Bytecount translen;
613
614 memcpy (trans, XSTRING_DATA (ctext), XSTRING_LENGTH (ctext) + 1);
615 translen =
616 mswindows_translate_menu_or_dialog_item (trans,
617 XSTRING_LENGTH (ctext),
618 2 * XSTRING_LENGTH (ctext) + 3,
619 &accel_unused,
620 ctext);
621 push_bufbyte_string_as_unicode (template, trans, translen);
622 }
366 623
367 /* Specify 0 length creation data. */ 624 /* Specify 0 length creation data. */
368 Dynarr_add_many (template, &zeroes, 2); 625 Dynarr_add_many (template, &zeroes, 2);
369 626
370 item_tem.x += item_tem.cx + X_BUTTON_SPACING; 627 item_tem.x += item_tem.cx + X_BUTTON_SPACING;
371 } 628 }
372 } 629 }
373 630
374 /* Now the Windows dialog structure is ready. We need to prepare a 631 /* Now the Windows dialog structure is ready. We need to prepare a
375 data structure for the new dialog, which will contain callbacks 632 data structure for the new dialog, which will contain callbacks
376 and the frame for these callbacks. This structure has to be 633 and the frame for these callbacks. This structure has to be
377 GC-protected. The data structure itself is a cons of frame object 634 GC-protected and thus it is put into a statically protected
378 and a vector of callbacks; for the protection reasons it is put 635 list. */
379 into a statically protected list. */
380 { 636 {
381 Lisp_Object frame, vector, dialog_data; 637 Lisp_Object dialog_data;
382 int i; 638 int i;
639 struct mswindows_dialog_id *did =
640 alloc_lcrecord_type (struct mswindows_dialog_id,
641 &lrecord_mswindows_dialog_id);
642
643 XSETMSWINDOWS_DIALOG_ID (dialog_data, did);
644
645 did->frame = wrap_frame (f);
646 did->callbacks = make_vector (Dynarr_length (dialog_items), Qunbound);
647 for (i = 0; i < Dynarr_length (dialog_items); i++)
648 XVECTOR_DATA (did->callbacks) [i] =
649 XGUI_ITEM (*Dynarr_atp (dialog_items, i))->callback;
383 650
384 XSETFRAME (frame, f);
385 vector = make_vector (Dynarr_length (dialog_items), Qunbound);
386 dialog_data = Fcons (frame, vector);
387 for (i = 0; i < Dynarr_length (dialog_items); i++)
388 XVECTOR_DATA (vector) [i] = XGUI_ITEM (*Dynarr_atp (dialog_items, i))->callback;
389
390 /* Woof! Everything is ready. Pop pop pop in now! */ 651 /* Woof! Everything is ready. Pop pop pop in now! */
391 if (!CreateDialogIndirectParam (NULL, 652 did->hwnd =
392 (LPDLGTEMPLATE) Dynarr_atp (template, 0), 653 CreateDialogIndirectParam (NULL,
393 FRAME_MSWINDOWS_HANDLE (f), dialog_proc, 654 (LPDLGTEMPLATE) Dynarr_atp (template, 0),
394 (LPARAM) LISP_TO_VOID (dialog_data))) 655 FRAME_MSWINDOWS_HANDLE (f), dialog_proc,
656 (LPARAM) LISP_TO_VOID (dialog_data));
657 if (!did->hwnd)
395 /* Something went wrong creating the dialog */ 658 /* Something went wrong creating the dialog */
396 signal_simple_error ("System error creating dialog", desc); 659 signal_type_error (Qdialog_box_error, "Creating dialog", keys);
397 660
398 Vdialog_data_list = Fcons (dialog_data, Vdialog_data_list); 661 Vdialog_data_list = Fcons (dialog_data, Vdialog_data_list);
662
663 /* Cease protection and free dynarrays */
664 unbind_to (unbind_count, Qnil);
665 return dialog_data;
399 } 666 }
400 667 }
401 /* Cease protection and free dynarrays */ 668
402 unbind_to (unbind_count, Qnil); 669 static Lisp_Object
670 mswindows_make_dialog_box_internal (struct frame* f, Lisp_Object type,
671 Lisp_Object keys)
672 {
673 if (EQ (type, Qfile))
674 return handle_file_dialog_box (f, keys);
675 else if (EQ (type, Qquestion))
676 return handle_question_dialog_box (f, keys);
677 else if (EQ (type, Qprint))
678 return mswindows_handle_print_dialog_box (f, keys);
679 else if (EQ (type, Qpage_setup))
680 return mswindows_handle_page_setup_dialog_box (f, keys);
681 else if (EQ (type, Qprint_setup))
682 return mswindows_handle_print_setup_dialog_box (f, keys);
683 else
684 signal_type_error (Qunimplemented, "Dialog box type", type);
685 return Qnil;
403 } 686 }
404 687
405 void 688 void
406 console_type_create_dialog_mswindows (void) 689 console_type_create_dialog_mswindows (void)
407 { 690 {
408 CONSOLE_HAS_METHOD (mswindows, popup_dialog_box); 691 CONSOLE_HAS_METHOD (mswindows, make_dialog_box_internal);
692 }
693
694 void
695 syms_of_dialog_mswindows (void)
696 {
697 INIT_LRECORD_IMPLEMENTATION (mswindows_dialog_id);
698
699 DEFKEYWORD (Q_initial_directory);
700 DEFKEYWORD (Q_initial_filename);
701 DEFKEYWORD (Q_filter_list);
702 DEFKEYWORD (Q_title);
703 DEFKEYWORD (Q_allow_multi_select);
704 DEFKEYWORD (Q_create_prompt_on_nonexistent);
705 DEFKEYWORD (Q_overwrite_prompt);
706 DEFKEYWORD (Q_file_must_exist);
707 DEFKEYWORD (Q_no_network_button);
708 DEFKEYWORD (Q_no_read_only_return);
709
710 /* Errors */
711 DEFERROR_STANDARD (Qdialog_box_error, Qinvalid_operation);
409 } 712 }
410 713
411 void 714 void
412 vars_of_dialog_mswindows (void) 715 vars_of_dialog_mswindows (void)
413 { 716 {
717 Vpopup_frame_list = Qnil;
718 staticpro (&Vpopup_frame_list);
719
414 Vdialog_data_list = Qnil; 720 Vdialog_data_list = Qnil;
415 staticpro (&Vdialog_data_list); 721 staticpro (&Vdialog_data_list);
416 } 722
723 DEFVAR_LISP ("default-file-dialog-filter-alist",
724 &Vdefault_file_dialog_filter_alist /*
725 */ );
726 Vdefault_file_dialog_filter_alist =
727 list5 (Fcons (build_string ("Text Files"), build_string ("*.txt")),
728 Fcons (build_string ("C Files"), build_string ("*.c;*.h")),
729 Fcons (build_string ("Elisp Files"), build_string ("*.el")),
730 Fcons (build_string ("HTML Files"), build_string ("*.html;*.html")),
731 Fcons (build_string ("All Files"), build_string ("*.*")));
732 }