"main_menu.[ch]" -> "menus.[ch]"; it handles not only the main menu, but
[obnox/wireshark/wip.git] / gtk / file_dlg_win32.c
1 /* win32-file-dlg.c
2  * Native Windows file dialog routines
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 2004 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdio.h>
30 #include <tchar.h>
31 #include <wchar.h>
32 #include <stdlib.h>
33 #include <sys/stat.h>
34 #include <io.h>
35 #include <fcntl.h>
36
37 #include <windows.h>
38 #include <windowsx.h>
39 #include <commdlg.h>
40 #include <richedit.h>
41
42
43 #include <gtk/gtk.h>
44
45 #include "epan/filesystem.h"
46 #include "epan/addr_resolv.h"
47 #include "epan/prefs.h"
48 #include "wsutil/file_util.h"
49 #include "wsutil/unicode-utils.h"
50
51 #include "../globals.h"
52 #include "../alert_box.h"
53 #include "../color.h"
54 #include "../print.h"
55 #include "../simple_dialog.h"
56 #include "../util.h"
57 #include "../color_filters.h"
58 #include "../merge.h"
59
60 #include "gtk/file_dlg.h"
61 #include "gtk/capture_file_dlg.h"
62 #include "gtk/main.h"
63 #include "gtk/menus.h"
64 #include "gtk/drag_and_drop.h"
65 #include "gtk/capture_dlg.h"
66 #include "gtk/file_dlg_win32.h"
67 #include "gtk/help_dlg.h"
68
69 typedef enum {
70     merge_append,
71     merge_chrono,
72     merge_prepend
73 } merge_action_e;
74
75 #define FILE_OPEN_DEFAULT 1 /* All Files */
76
77 #define FILE_MERGE_DEFAULT FILE_OPEN_DEFAULT
78
79 #define FILE_SAVE_DEFAULT 1 /* Wireshark/tcpdump */
80
81 #define FILE_TYPES_EXPORT \
82     _T("Plain text (*.txt)\0")                           _T("*.txt\0")   \
83     _T("PostScript (*.ps)\0")                            _T("*.ps\0")    \
84     _T("CSV (Comma Separated Values summary) (*.csv)\0") _T("*.csv\0")   \
85     _T("PSML (XML packet summary) (*.psml)\0")           _T("*.psml\0")  \
86     _T("PDML (XML packet detail) (*.pdml)\0")            _T("*.pdml\0")  \
87     _T("C Arrays (packet bytes) (*.c)\0")                _T("*.c\0")
88
89 #define FILE_TYPES_RAW \
90     _T("Raw data (*.bin, *.dat, *.raw)\0")               _T("*.bin;*.dat;*.raw\0") \
91     _T("All Files (*.*)\0")                              _T("*.*\0")
92
93 #define FILE_RAW_DEFAULT 1
94
95 #define FILE_TYPES_COLOR \
96     _T("Text Files (*.txt)\0")                           _T("*.txt\0")   \
97     _T("All Files (*.*)\0")                              _T("*.*\0")
98
99 #define FILE_DEFAULT_COLOR 2
100
101 /*
102  * We should probably test the SDK version instead of the compiler version,
103  * but this should work for our purposes.
104  */
105 #if (_MSC_VER <= 1200)
106 static UINT CALLBACK open_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
107 static UINT CALLBACK save_as_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
108 static UINT CALLBACK merge_file_hook_proc(HWND mf_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
109 static UINT CALLBACK export_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
110 static UINT CALLBACK export_raw_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
111 #else
112 static UINT_PTR CALLBACK open_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
113 static UINT_PTR CALLBACK save_as_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
114 static UINT_PTR CALLBACK merge_file_hook_proc(HWND mf_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
115 static UINT_PTR CALLBACK export_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
116 static UINT_PTR CALLBACK export_raw_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
117 #endif /* (_MSC_VER <= 1200) */
118
119 static void range_update_dynamics(HWND sf_hwnd, packet_range_t *range);
120 static void range_handle_wm_initdialog(HWND dlg_hwnd, packet_range_t *range);
121 static void range_handle_wm_command(HWND dlg_hwnd, HWND ctrl, WPARAM w_param, packet_range_t *range);
122
123 static TCHAR *build_file_type_list(gboolean save, int *item_to_select);
124 static int file_type_from_list_index(gboolean save, int index);
125
126 static int            filetype;
127 static packet_range_t range;
128 static merge_action_e merge_action;
129 static print_args_t   print_args;
130 /* XXX - The reason g_sf_hwnd exists is so that we can call
131  *       range_update_dynamics() from anywhere; it's currently
132  *       static, but if we move to using the native Windows
133  *       print dialog and put range widgets in it as well,
134  *       it might be moved to a separate file.
135  *
136  *       However, the save file dialog hogs the foreground, so
137  *       this may not be necessary (and, in fact, the file dialogs
138  *       should arguably be modal to the window for the file
139  *       being opened/saved/etc.).
140  */
141 static HWND           g_sf_hwnd = NULL;
142 char *dfilter_open_str = NULL;
143 char *dfilter_merge_str = NULL;
144
145 gboolean
146 win32_open_file (HWND h_wnd) {
147     OPENFILENAME *ofn;
148     TCHAR  file_name[MAX_PATH] = _T("");
149     int    err;
150     char  *dirname;
151     dfilter_t *dfp;
152     int    ofnsize;
153 #if (_MSC_VER >= 1500)
154     OSVERSIONINFO osvi;
155 #endif
156
157     /* Remarks on OPENFILENAME_SIZE_VERSION_400:
158      *
159      * MSDN states that OPENFILENAME_SIZE_VERSION_400 should be used with
160      * WINVER and _WIN32_WINNT >= 0x0500.
161      * Unfortunately all these are compiler constants, while the underlying is a
162      * problem based is a length check of the runtime version used.
163      *
164      * Instead of using OPENFILENAME_SIZE_VERSION_400, just malloc
165      * the OPENFILENAME size plus 12 bytes.
166      * These 12 bytes are the difference between the two versions of this struct.
167      *
168      * Interestingly this fixes a bug, so the places bar e.g. "My Documents"
169      * is displayed - which wasn't the case with the former implementation.
170      *
171      * XXX - It's unclear if this length+12 works on all supported platforms,
172      * NT4 is the question here. However, even if it fails, we must calculate
173      * the length based on the runtime, not the compiler version anyway ...
174      */
175     /* This assumption does not work when compiling with MSVC2008EE as
176      * the open dialog window does not appear.
177      * Instead detect Windows version at runtime and choose size accordingly */
178 #if (_MSC_VER >= 1500)
179     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
180     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
181     GetVersionEx(&osvi);
182     if (osvi.dwMajorVersion >= 5) {
183         ofnsize = sizeof(OPENFILENAME);
184     } else {
185         ofnsize = OPENFILENAME_SIZE_VERSION_400;
186     }
187 #else
188     ofnsize = sizeof(OPENFILENAME) + 12;
189 #endif
190     ofn = g_malloc0(ofnsize);
191
192     ofn->lStructSize = ofnsize;
193     ofn->hwndOwner = h_wnd;
194 #if (_MSC_VER <= 1200)
195     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
196 #else
197     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
198 #endif
199     ofn->lpstrFilter = build_file_type_list(FALSE /*!save*/, NULL);
200     ofn->lpstrCustomFilter = NULL;
201     ofn->nMaxCustFilter = 0;
202     ofn->nFilterIndex = FILE_OPEN_DEFAULT;
203     ofn->lpstrFile = file_name;
204     ofn->nMaxFile = MAX_PATH;
205     ofn->lpstrFileTitle = NULL;
206     ofn->nMaxFileTitle = 0;
207     if (prefs.gui_fileopen_style == FO_STYLE_SPECIFIED && prefs.gui_fileopen_dir[0] != '\0') {
208         ofn->lpstrInitialDir = utf_8to16(prefs.gui_fileopen_dir);
209     } else {
210         ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
211     }
212     ofn->lpstrTitle = _T("Wireshark: Open Capture File");
213     ofn->Flags = OFN_ENABLESIZING | OFN_ENABLETEMPLATE | OFN_EXPLORER     |
214                  OFN_NOCHANGEDIR  | OFN_FILEMUSTEXIST  | OFN_HIDEREADONLY |
215                  OFN_ENABLEHOOK   | OFN_SHOWHELP;
216     ofn->lpstrDefExt = NULL;
217     ofn->lpfnHook = open_file_hook_proc;
218     ofn->lpTemplateName = _T("WIRESHARK_OPENFILENAME_TEMPLATE");
219
220     if (GetOpenFileName(ofn)) {
221         g_free( (void *) ofn->lpstrFilter);
222         g_free( (void *) ofn);
223
224         if (cf_open(&cfile, utf_16to8(file_name), FALSE, &err) != CF_OK) {
225             return FALSE;
226         }
227
228         /* apply our filter */
229         if (dfilter_compile(dfilter_open_str, &dfp)) {
230             cf_set_rfcode(&cfile, dfp);
231         }
232
233         switch (cf_read(&cfile)) {
234             case CF_READ_OK:
235             case CF_READ_ERROR:
236                 dirname = get_dirname(utf_16to8(file_name));
237                 set_last_open_dir(dirname);
238                 return TRUE;
239                 break;
240         }
241     } else {
242         g_free( (void *) ofn->lpstrFilter);
243         g_free( (void *) ofn);
244     }
245     return FALSE;
246 }
247
248
249 void
250 win32_save_as_file(HWND h_wnd, action_after_save_e action_after_save, gpointer action_after_save_data) {
251     OPENFILENAME *ofn;
252     TCHAR  file_name16[MAX_PATH] = _T("");
253     GString *file_name8;
254     gchar *file_last_dot;
255     gchar *dirname;
256     int save_index;
257     int    ofnsize;
258 #if (_MSC_VER >= 1500)
259     OSVERSIONINFO osvi;
260 #endif
261
262     /* see OPENFILENAME comment in win32_open_file */
263 #if (_MSC_VER >= 1500)
264     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
265     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
266     GetVersionEx(&osvi);
267     if (osvi.dwMajorVersion >= 5) {
268         ofnsize = sizeof(OPENFILENAME);
269     } else {
270         ofnsize = OPENFILENAME_SIZE_VERSION_400;
271     }
272 #else
273     ofnsize = sizeof(OPENFILENAME) + 12;
274 #endif
275     ofn = g_malloc0(ofnsize);
276
277     ofn->lStructSize = ofnsize;
278     ofn->hwndOwner = h_wnd;
279 #if (_MSC_VER <= 1200)
280     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
281 #else
282     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
283 #endif
284     ofn->lpstrFilter = build_file_type_list(TRUE /*save*/, &save_index);
285     ofn->lpstrCustomFilter = NULL;
286     ofn->nMaxCustFilter = 0;
287     ofn->nFilterIndex = save_index;
288     ofn->lpstrFile = file_name16;
289     ofn->nMaxFile = MAX_PATH;
290     ofn->lpstrFileTitle = NULL;
291     ofn->nMaxFileTitle = 0;
292     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
293     ofn->lpstrTitle = _T("Wireshark: Save file as");
294     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
295                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
296                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
297     ofn->lpstrDefExt = NULL;
298     ofn->lpfnHook = save_as_file_hook_proc;
299     ofn->lpTemplateName = _T("WIRESHARK_SAVEFILENAME_TEMPLATE");
300
301     if (GetSaveFileName(ofn)) {
302         filetype = file_type_from_list_index(TRUE /*save*/, ofn->nFilterIndex);
303
304         /* append the default file extension if there's none given by the user */
305         /* (we expect a file extension to be at most 5 chars + the dot) */
306         file_name8 = g_string_new(utf_16to8(file_name16));
307         file_last_dot = strrchr(file_name8->str,'.');
308         if(file_last_dot == NULL || strlen(file_name8->str)-(file_last_dot-file_name8->str) > 5+1) {
309             if(wtap_file_extension_default_string(filetype) != NULL) {
310                 file_name8 = g_string_append(file_name8, wtap_file_extension_default_string(filetype));
311             }
312         }
313
314         g_sf_hwnd = NULL;
315         /* Write out the packets (all, or only the ones from the current
316            range) to the file with the specified name. */
317
318         /* GetSaveFileName() already asked the user if he wants to overwrite the old file,        */
319         /* so if we are here, user already confirmed to overwrite - just delete the old file now. */
320         ws_unlink(file_name8->str);  /* XX: Windows Wireshark is built with GLIB >= 2.6 these     */
321                                      /* days so ws_unlink will properly convert the               */
322                                      /* UTF8 filename to UTF16 & then do a _wunlink.              */
323
324         if (cf_save(&cfile, file_name8->str, &range, filetype, FALSE) != CF_OK) {
325             /* The write failed.  Try again. */
326             g_string_free(file_name8, TRUE /* free_segment */);
327             g_free( (void *) ofn->lpstrFilter);
328             g_free( (void *) ofn);
329             win32_save_as_file(h_wnd, action_after_save, action_after_save_data);
330             return;
331         }
332
333         /* Save the directory name for future file dialogs. */
334         dirname = get_dirname(file_name8->str);  /* Overwrites cf_name */
335         set_last_open_dir(dirname);
336
337         g_string_free(file_name8, TRUE /* free_segment */);
338
339         /* we have finished saving, do we have pending things to do? */
340         switch(action_after_save) {
341             case(after_save_no_action):
342                 break;
343             case(after_save_open_dialog):
344                 win32_open_file(h_wnd);
345                 break;
346             case(after_save_open_recent_file):
347                 menu_open_recent_file_cmd(action_after_save_data);
348                 break;
349             case(after_save_open_dnd_file):
350                 dnd_open_file_cmd(action_after_save_data);
351                 break;
352             case(after_save_merge_dialog):
353                 win32_merge_file(h_wnd);
354                 break;
355 #ifdef HAVE_LIBPCAP
356             case(after_save_capture_dialog):
357                 capture_start_confirmed();
358                 break;
359 #endif
360             case(after_save_close_file):
361                 cf_close(&cfile);
362                 break;
363             case(after_save_exit):
364                 main_do_quit();
365                 break;
366             default:
367                 g_assert_not_reached();
368         }
369     }
370     g_sf_hwnd = NULL;
371     g_free( (void *) ofn->lpstrFilter);
372     g_free( (void *) ofn);
373 }
374
375
376 void
377 win32_merge_file (HWND h_wnd) {
378     OPENFILENAME *ofn;
379     TCHAR       file_name[MAX_PATH] = _T("");
380     char       *dirname;
381     cf_status_t merge_status;
382     char       *in_filenames[2];
383     int         err;
384     char       *tmpname;
385     dfilter_t  *dfp;
386     int         ofnsize;
387 #if (_MSC_VER >= 1500)
388     OSVERSIONINFO osvi;
389 #endif
390
391     /* see OPENFILENAME comment in win32_open_file */
392 #if (_MSC_VER >= 1500)
393     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
394     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
395     GetVersionEx(&osvi);
396     if (osvi.dwMajorVersion >= 5) {
397         ofnsize = sizeof(OPENFILENAME);
398     } else {
399         ofnsize = OPENFILENAME_SIZE_VERSION_400;
400     }
401 #else
402     ofnsize = sizeof(OPENFILENAME) + 12;
403 #endif
404     ofn = g_malloc0(ofnsize);
405
406     ofn->lStructSize = ofnsize;
407     ofn->hwndOwner = h_wnd;
408 #if (_MSC_VER <= 1200)
409     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
410 #else
411     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
412 #endif
413     ofn->lpstrFilter = build_file_type_list(FALSE /*!save*/, NULL);
414     ofn->lpstrCustomFilter = NULL;
415     ofn->nMaxCustFilter = 0;
416     ofn->nFilterIndex = FILE_MERGE_DEFAULT;
417     ofn->lpstrFile = file_name;
418     ofn->nMaxFile = MAX_PATH;
419     ofn->lpstrFileTitle = NULL;
420     ofn->nMaxFileTitle = 0;
421     if (prefs.gui_fileopen_style == FO_STYLE_SPECIFIED && prefs.gui_fileopen_dir[0] != '\0') {
422         ofn->lpstrInitialDir = utf_8to16(prefs.gui_fileopen_dir);
423     } else {
424         ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
425     }
426     ofn->lpstrTitle = _T("Wireshark: Merge with capture file");
427     ofn->Flags = OFN_ENABLESIZING | OFN_ENABLETEMPLATE | OFN_EXPLORER     |
428                  OFN_NOCHANGEDIR  | OFN_FILEMUSTEXIST  | OFN_HIDEREADONLY |
429                  OFN_ENABLEHOOK   | OFN_SHOWHELP;
430     ofn->lpstrDefExt = NULL;
431     ofn->lpfnHook = merge_file_hook_proc;
432     ofn->lpTemplateName = _T("WIRESHARK_MERGEFILENAME_TEMPLATE");
433
434     if (GetOpenFileName(ofn)) {
435         filetype = cfile.cd_t;
436         g_free( (void *) ofn->lpstrFilter);
437         g_free( (void *) ofn);
438
439         /* merge or append the two files */
440
441         tmpname = NULL;
442         switch (merge_action) {
443             case merge_append:
444                 /* append file */
445                 in_filenames[0] = cfile.filename;
446                 in_filenames[1] = utf_16to8(file_name);
447                 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype, TRUE);
448                 break;
449             case merge_chrono:
450                 /* chonological order */
451                 in_filenames[0] = cfile.filename;
452                 in_filenames[1] = utf_16to8(file_name);
453                 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype, FALSE);
454                 break;
455             case merge_prepend:
456                 /* prepend file */
457                 in_filenames[0] = utf_16to8(file_name);
458                 in_filenames[1] = cfile.filename;
459                 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype, TRUE);
460                 break;
461             default:
462                 g_assert_not_reached();
463         }
464
465         if(merge_status != CF_OK) {
466             /* merge failed */
467             g_free(tmpname);
468             return;
469         }
470
471         cf_close(&cfile);
472
473         /* Try to open the merged capture file. */
474         if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) != CF_OK) {
475             /* We couldn't open it; don't dismiss the open dialog box,
476                just leave it around so that the user can, after they
477                dismiss the alert box popped up for the open error,
478                try again. */
479             return;
480         }
481
482         /* apply our filter */
483         if (dfilter_compile(dfilter_merge_str, &dfp)) {
484             cf_set_rfcode(&cfile, dfp);
485         }
486
487         switch (cf_read(&cfile)) {
488             case CF_READ_OK:
489             case CF_READ_ERROR:
490                 dirname = get_dirname(utf_16to8(file_name));
491                 set_last_open_dir(dirname);
492                 menu_name_resolution_changed();
493                 break;
494             case CF_READ_ABORTED:
495                 break;
496         }
497     } else {
498         g_free( (void *) ofn->lpstrFilter);
499         g_free( (void *) ofn);
500     }
501 }
502
503 void
504 win32_export_file(HWND h_wnd, export_type_e export_type) {
505     OPENFILENAME     *ofn;
506     TCHAR             file_name[MAX_PATH] = _T("");
507     char             *dirname;
508     cf_print_status_t status;
509     int               ofnsize;
510 #if (_MSC_VER >= 1500)
511     OSVERSIONINFO osvi;
512 #endif
513
514     /* see OPENFILENAME comment in win32_open_file */
515 #if (_MSC_VER >= 1500)
516     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
517     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
518     GetVersionEx(&osvi);
519     if (osvi.dwMajorVersion >= 5) {
520         ofnsize = sizeof(OPENFILENAME);
521     } else {
522         ofnsize = OPENFILENAME_SIZE_VERSION_400;
523     }
524 #else
525     ofnsize = sizeof(OPENFILENAME) + 12;
526 #endif
527     ofn = g_malloc0(ofnsize);
528
529     ofn->lStructSize = ofnsize;
530     ofn->hwndOwner = h_wnd;
531 #if (_MSC_VER <= 1200)
532     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
533 #else
534     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
535 #endif
536     ofn->lpstrFilter = FILE_TYPES_EXPORT;
537     ofn->lpstrCustomFilter = NULL;
538     ofn->nMaxCustFilter = 0;
539     ofn->nFilterIndex = export_type;
540     ofn->lpstrFile = file_name;
541     ofn->nMaxFile = MAX_PATH;
542     ofn->lpstrFileTitle = NULL;
543     ofn->nMaxFileTitle = 0;
544     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
545     ofn->lpstrTitle = _T("Wireshark: Export File");
546     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
547                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
548                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
549     ofn->lpstrDefExt = NULL;
550     ofn->lpfnHook = export_file_hook_proc;
551     ofn->lpTemplateName = _T("WIRESHARK_EXPORTFILENAME_TEMPLATE");
552
553     /* Fill in our print (and export) args */
554
555     print_args.format              = PR_FMT_TEXT;
556     print_args.to_file             = TRUE;
557     print_args.cmd                 = NULL;
558     print_args.print_summary       = TRUE;
559     print_args.print_dissections   = print_dissections_as_displayed;
560     print_args.print_hex           = FALSE;
561     print_args.print_formfeed      = FALSE;
562
563     if (GetSaveFileName(ofn)) {
564         print_args.file = utf_16to8(file_name);
565         switch (ofn->nFilterIndex) {
566             case export_type_text:      /* Text */
567                 print_args.stream = print_stream_text_new(TRUE, print_args.file);
568                 if (print_args.stream == NULL) {
569                     open_failure_alert_box(print_args.file, errno, TRUE);
570                     g_free( (void *) ofn);
571                     return;
572                 }
573                 status = cf_print_packets(&cfile, &print_args);
574                 break;
575             case export_type_ps:        /* PostScript (r) */
576                 print_args.stream = print_stream_ps_new(TRUE, print_args.file);
577                 if (print_args.stream == NULL) {
578                     open_failure_alert_box(print_args.file, errno, TRUE);
579                     g_free( (void *) ofn);
580                     return;
581                 }
582                 status = cf_print_packets(&cfile, &print_args);
583                 break;
584             case export_type_csv:       /* CSV */
585                 status = cf_write_csv_packets(&cfile, &print_args);
586                 break;
587             case export_type_carrays:   /* C Arrays */
588                 status = cf_write_carrays_packets(&cfile, &print_args);
589                 break;
590             case export_type_psml:      /* PSML */
591                 status = cf_write_psml_packets(&cfile, &print_args);
592                 break;
593             case export_type_pdml:      /* PDML */
594                 status = cf_write_pdml_packets(&cfile, &print_args);
595                 break;
596             default:
597                 g_free( (void *) ofn);
598                 return;
599         }
600
601         switch (status) {
602             case CF_PRINT_OK:
603                 break;
604             case CF_PRINT_OPEN_ERROR:
605                 open_failure_alert_box(print_args.file, errno, TRUE);
606                 break;
607             case CF_PRINT_WRITE_ERROR:
608                 write_failure_alert_box(print_args.file, errno);
609                 break;
610         }
611         /* Save the directory name for future file dialogs. */
612         dirname = get_dirname(utf_16to8(file_name));  /* Overwrites cf_name */
613         set_last_open_dir(dirname);
614     }
615
616     g_free( (void *) ofn);
617 }
618
619 void
620 win32_export_raw_file(HWND h_wnd) {
621     OPENFILENAME *ofn;
622     TCHAR         file_name[MAX_PATH] = _T("");
623     char         *dirname;
624     const guint8 *data_p;
625     char         *file_name8;
626     int           fd;
627     int           ofnsize;
628 #if (_MSC_VER >= 1500)
629     OSVERSIONINFO osvi;
630 #endif
631
632     if (!cfile.finfo_selected) {
633         /* This shouldn't happen */
634         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No bytes were selected.");
635         return;
636     }
637
638     /* see OPENFILENAME comment in win32_open_file */
639 #if (_MSC_VER >= 1500)
640     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
641     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
642     GetVersionEx(&osvi);
643     if (osvi.dwMajorVersion >= 5) {
644         ofnsize = sizeof(OPENFILENAME);
645     } else {
646         ofnsize = OPENFILENAME_SIZE_VERSION_400;
647     }
648 #else
649     ofnsize = sizeof(OPENFILENAME) + 12;
650 #endif
651     ofn = g_malloc0(ofnsize);
652
653     ofn->lStructSize = ofnsize;
654     ofn->hwndOwner = h_wnd;
655 #if (_MSC_VER <= 1200)
656     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
657 #else
658     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
659 #endif
660     ofn->lpstrFilter = FILE_TYPES_RAW;
661     ofn->lpstrCustomFilter = NULL;
662     ofn->nMaxCustFilter = 0;
663     ofn->nFilterIndex = FILE_RAW_DEFAULT;
664     ofn->lpstrFile = file_name;
665     ofn->nMaxFile = MAX_PATH;
666     ofn->lpstrFileTitle = NULL;
667     ofn->nMaxFileTitle = 0;
668     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
669     ofn->lpstrTitle = _T("Wireshark: Export Raw Data");
670     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
671                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
672                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
673     ofn->lpstrDefExt = NULL;
674     ofn->lCustData = cfile.finfo_selected->length;
675     ofn->lpfnHook = export_raw_file_hook_proc;
676     ofn->lpTemplateName = _T("WIRESHARK_EXPORTRAWFILENAME_TEMPLATE");
677
678     /*
679      * XXX - The GTK+ code uses get_byte_view_data_and_length().  We just
680      * grab the info from cfile.finfo_selected.  Which is more "correct"?
681      */
682
683     if (GetSaveFileName(ofn)) {
684         g_free( (void *) ofn);
685         file_name8 = utf_16to8(file_name);
686         data_p = tvb_get_ptr(cfile.finfo_selected->ds_tvb, 0, -1) +
687                 cfile.finfo_selected->start;
688         fd = ws_open(file_name8, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
689         if (fd == -1) {
690             open_failure_alert_box(file_name8, errno, TRUE);
691             return;
692         }
693         if (write(fd, data_p, cfile.finfo_selected->length) < 0) {
694             write_failure_alert_box(file_name8, errno);
695             close(fd);
696             return;
697         }
698         if (close(fd) < 0) {
699             write_failure_alert_box(file_name8, errno);
700             return;
701         }
702
703         /* Save the directory name for future file dialogs. */
704         dirname = get_dirname(file_name8);  /* Overwrites cf_name */
705         set_last_open_dir(dirname);
706     } else {
707         g_free( (void *) ofn);
708     }
709 }
710
711 void
712 win32_export_color_file(HWND h_wnd, gpointer filter_list) {
713     OPENFILENAME *ofn;
714     TCHAR  file_name[MAX_PATH] = _T("");
715     gchar *dirname;
716     int    ofnsize;
717 #if (_MSC_VER >= 1500)
718     OSVERSIONINFO osvi;
719 #endif
720
721     /* see OPENFILENAME comment in win32_open_file */
722 #if (_MSC_VER >= 1500)
723     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
724     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
725     GetVersionEx(&osvi);
726     if (osvi.dwMajorVersion >= 5) {
727         ofnsize = sizeof(OPENFILENAME);
728     } else {
729         ofnsize = OPENFILENAME_SIZE_VERSION_400;
730     }
731 #else
732     ofnsize = sizeof(OPENFILENAME) + 12;
733 #endif
734     ofn = g_malloc0(ofnsize);
735
736     ofn->lStructSize = ofnsize;
737     ofn->hwndOwner = h_wnd;
738 #if (_MSC_VER <= 1200)
739     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
740 #else
741     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
742 #endif
743     ofn->lpstrFilter = FILE_TYPES_COLOR;
744     ofn->lpstrCustomFilter = NULL;
745     ofn->nMaxCustFilter = 0;
746     ofn->nFilterIndex = FILE_DEFAULT_COLOR;
747     ofn->lpstrFile = file_name;
748     ofn->nMaxFile = MAX_PATH;
749     ofn->lpstrFileTitle = NULL;
750     ofn->nMaxFileTitle = 0;
751     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
752     ofn->lpstrTitle = _T("Wireshark: Export Color Filters");
753     ofn->Flags = OFN_ENABLESIZING  | OFN_EXPLORER        |
754                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
755                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK;
756     ofn->lpstrDefExt = NULL;
757     ofn->lpfnHook = NULL;
758     ofn->lpTemplateName = NULL;
759
760     filetype = cfile.cd_t;
761
762     /* XXX - Support marked filters */
763     if (GetSaveFileName(ofn)) {
764         g_free( (void *) ofn);
765         if (!color_filters_export(utf_16to8(file_name), filter_list, FALSE /* all filters */))
766             return;
767
768         /* Save the directory name for future file dialogs. */
769         dirname = get_dirname(utf_16to8(file_name));  /* Overwrites cf_name */
770         set_last_open_dir(dirname);
771     } else {
772         g_free( (void *) ofn);
773     }
774 }
775
776 void
777 win32_import_color_file(HWND h_wnd, gpointer color_filters) {
778     OPENFILENAME *ofn;
779     TCHAR  file_name[MAX_PATH] = _T("");
780     gchar *dirname;
781     int    ofnsize;
782 #if (_MSC_VER >= 1500)
783     OSVERSIONINFO osvi;
784 #endif
785
786     /* see OPENFILENAME comment in win32_open_file */
787 #if (_MSC_VER >= 1500)
788     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
789     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
790     GetVersionEx(&osvi);
791     if (osvi.dwMajorVersion >= 5) {
792         ofnsize = sizeof(OPENFILENAME);
793     } else {
794         ofnsize = OPENFILENAME_SIZE_VERSION_400;
795     }
796 #else
797     ofnsize = sizeof(OPENFILENAME) + 12;
798 #endif
799     ofn = g_malloc0(ofnsize);
800
801     ofn->lStructSize = ofnsize;
802     ofn->hwndOwner = h_wnd;
803 #if (_MSC_VER <= 1200)
804     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
805 #else
806     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
807 #endif
808     ofn->lpstrFilter = FILE_TYPES_COLOR;
809     ofn->lpstrCustomFilter = NULL;
810     ofn->nMaxCustFilter = 0;
811     ofn->nFilterIndex = FILE_DEFAULT_COLOR;
812     ofn->lpstrFile = file_name;
813     ofn->nMaxFile = MAX_PATH;
814     ofn->lpstrFileTitle = NULL;
815     ofn->nMaxFileTitle = 0;
816     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
817     ofn->lpstrTitle = _T("Wireshark: Import Color Filters");
818     ofn->Flags = OFN_ENABLESIZING  | OFN_EXPLORER        |
819                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
820                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK;
821     ofn->lpstrDefExt = NULL;
822     ofn->lpfnHook = NULL;
823     ofn->lpTemplateName = NULL;
824
825     /* XXX - Support export limited to selected filters */
826     if (GetOpenFileName(ofn)) {
827         g_free( (void *) ofn);
828         if (!color_filters_import(utf_16to8(file_name), color_filters))
829             return;
830
831         /* Save the directory name for future file dialogs. */
832         dirname = get_dirname(utf_16to8(file_name));  /* Overwrites cf_name */
833         set_last_open_dir(dirname);
834     } else {
835         g_free( (void *) ofn);
836     }
837 }
838
839
840 /*
841  * Private routines
842  */
843 static void
844 format_handle_wm_initdialog(HWND dlg_hwnd, print_args_t *args) {
845     HWND cur_ctrl;
846
847     /* Set the "Packet summary" box */
848     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_SUMMARY_CB);
849     SendMessage(cur_ctrl, BM_SETCHECK, args->print_summary, 0);
850
851     /* Set the "Packet details" box */
852     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_CB);
853     SendMessage(cur_ctrl, BM_SETCHECK, args->print_dissections != print_dissections_none, 0);
854
855     /* Set the "Packet details" combo */
856     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_COMBO);
857     SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("All collapsed"));
858     SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("As displayed"));
859     SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("All expanded"));
860
861     switch (args->print_dissections) {
862         case print_dissections_none:
863         case print_dissections_collapsed:
864             SendMessage(cur_ctrl, CB_SETCURSEL, 0, 0);
865             break;
866         case print_dissections_as_displayed:
867             SendMessage(cur_ctrl, CB_SETCURSEL, 1, 0);
868             break;
869         case print_dissections_expanded:
870             SendMessage(cur_ctrl, CB_SETCURSEL, 2, 0);
871         default:
872             g_assert_not_reached();
873     }
874
875     /* Set the "Packet bytes" box */
876     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_BYTES_CB);
877     SendMessage(cur_ctrl, BM_SETCHECK, args->print_hex, 0);
878
879     /* Set the "Each packet on a new page" box */
880     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_NEW_PAGE_CB);
881     SendMessage(cur_ctrl, BM_SETCHECK, args->print_formfeed, 0);
882
883     print_update_dynamic(dlg_hwnd, args);
884 }
885
886 static void
887 print_update_dynamic(HWND dlg_hwnd, print_args_t *args) {
888     HWND cur_ctrl;
889
890     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_SUMMARY_CB);
891     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
892         args->print_summary = TRUE;
893     else
894         args->print_summary = FALSE;
895
896     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_CB);
897     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
898         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_COMBO);
899         switch (SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0)) {
900             case 0:
901                 args->print_dissections = print_dissections_collapsed;
902                 break;
903             case 1:
904                 args->print_dissections = print_dissections_as_displayed;
905                 break;
906             case 2:
907                 args->print_dissections = print_dissections_expanded;
908                 break;
909             default:
910                 g_assert_not_reached();
911         }
912         EnableWindow(cur_ctrl, TRUE);
913     } else {
914         args->print_dissections = print_dissections_none;
915         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_COMBO);
916         EnableWindow(cur_ctrl, FALSE);
917     }
918
919     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_BYTES_CB);
920     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
921         args->print_hex = TRUE;
922     else
923         args->print_hex = FALSE;
924
925     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_NEW_PAGE_CB);
926     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
927         args->print_formfeed = TRUE;
928     else
929         args->print_formfeed = FALSE;
930 }
931
932
933 #define PREVIEW_STR_MAX      200
934
935
936 /* If preview_file is NULL, disable the elements.  If not, enable and
937  * show the preview info. */
938 static gboolean
939 preview_set_filename(HWND of_hwnd, gchar *preview_file) {
940     HWND        cur_ctrl;
941     int         i;
942     gboolean    enable = FALSE;
943     wtap       *wth;
944     const struct wtap_pkthdr *phdr;
945     int         err = 0;
946     gchar      *err_info;
947     TCHAR       string_buff[PREVIEW_STR_MAX];
948     gint64      data_offset;
949     guint       packet = 0;
950     guint64     filesize;
951     time_t      ti_time;
952     struct tm  *ti_tm;
953     guint       elapsed_time;
954     time_t      time_preview;
955     time_t      time_current;
956     double      start_time = 0;
957     double      stop_time = 0;
958     double      cur_time;
959     gboolean    is_breaked = FALSE;
960
961     if (preview_file != NULL && strlen(preview_file) > 0) {
962         enable = TRUE;
963     }
964
965     for (i = EWFD_PT_FILENAME; i <= EWFD_PTX_ELAPSED; i++) {
966         cur_ctrl = GetDlgItem(of_hwnd, i);
967         if (cur_ctrl) {
968             EnableWindow(cur_ctrl, enable);
969         }
970     }
971
972     for (i = EWFD_PTX_FILENAME; i <= EWFD_PTX_ELAPSED; i++) {
973         cur_ctrl = GetDlgItem(of_hwnd, i);
974         if (cur_ctrl) {
975             SetWindowText(cur_ctrl, _T("-"));
976         }
977     }
978
979     if (enable) {
980         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FILENAME);
981         SetWindowText(cur_ctrl, utf_8to16(get_basename(preview_file)));
982
983         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FORMAT);
984         wth = wtap_open_offline(preview_file, &err, &err_info, TRUE);
985         if (cur_ctrl && wth == NULL) {
986             if(err == WTAP_ERR_FILE_UNKNOWN_FORMAT) {
987                 SetWindowText(cur_ctrl, _T("unknown file format"));
988             } else {
989                 SetWindowText(cur_ctrl, _T("error opening file"));
990             }
991             return FALSE;
992         }
993
994         /* size */
995         filesize = wtap_file_size(wth, &err);
996         _snwprintf(string_buff, PREVIEW_STR_MAX, _T("%") _T(PRIu64) _T(" bytes"), filesize);
997         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_SIZE);
998         SetWindowText(cur_ctrl, string_buff);
999
1000         /* type */
1001         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FORMAT);
1002         SetWindowText(cur_ctrl, utf_8to16(wtap_file_type_string(wtap_file_type(wth))));
1003
1004         time(&time_preview);
1005         while ( (wtap_read(wth, &err, &err_info, &data_offset)) ) {
1006             phdr = wtap_phdr(wth);
1007             cur_time = nstime_to_sec( (const nstime_t *) &phdr->ts );
1008             if(packet == 0) {
1009                 start_time  = cur_time;
1010                 stop_time = cur_time;
1011             }
1012             if (cur_time < start_time) {
1013                 start_time = cur_time;
1014             }
1015             if (cur_time > stop_time){
1016                 stop_time = cur_time;
1017             }
1018             packet++;
1019             if(packet%100 == 0) {
1020                 time(&time_current);
1021                 if(time_current-time_preview >= (time_t) prefs.gui_fileopen_preview) {
1022                     is_breaked = TRUE;
1023                     break;
1024                 }
1025             }
1026         }
1027
1028         if(err != 0) {
1029             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("error after reading %u packets"), packet);
1030             cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_PACKETS);
1031             SetWindowText(cur_ctrl, string_buff);
1032             wtap_close(wth);
1033             return TRUE;
1034         }
1035
1036         /* packet count */
1037         if(is_breaked) {
1038             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("more than %u packets (preview timeout)"), packet);
1039         } else {
1040             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("%u"), packet);
1041         }
1042         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_PACKETS);
1043         SetWindowText(cur_ctrl, string_buff);
1044
1045         /* first packet */
1046         ti_time = (long)start_time;
1047         ti_tm = localtime( &ti_time );
1048         if(ti_tm) {
1049             _snwprintf(string_buff, PREVIEW_STR_MAX,
1050                      _T("%04d-%02d-%02d %02d:%02d:%02d"),
1051                      ti_tm->tm_year + 1900,
1052                      ti_tm->tm_mon + 1,
1053                      ti_tm->tm_mday,
1054                      ti_tm->tm_hour,
1055                      ti_tm->tm_min,
1056                      ti_tm->tm_sec);
1057         } else {
1058             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("?"));
1059         }
1060         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FIRST_PKT);
1061         SetWindowText(cur_ctrl, string_buff);
1062
1063         /* elapsed time */
1064         elapsed_time = (unsigned int)(stop_time-start_time);
1065         if(elapsed_time/86400) {
1066             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("%02u days %02u:%02u:%02u"),
1067             elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
1068         } else {
1069             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("%02u:%02u:%02u"),
1070             elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
1071         }
1072         if(is_breaked) {
1073             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("unknown"));
1074         }
1075         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_ELAPSED);
1076         SetWindowText(cur_ctrl, string_buff);
1077
1078         wtap_close(wth);
1079     }
1080
1081     return TRUE;
1082
1083 }
1084
1085
1086 char *
1087 filter_tb_get(HWND hwnd) {
1088     TCHAR     *strval = NULL;
1089     gint       len;
1090     char *ret;
1091
1092     /* If filter_text is non-NULL, use it.  Otherwise, grab the text from
1093      * the window */
1094     len = GetWindowTextLength(hwnd);
1095     if (len > 0) {
1096         len++;
1097         strval = g_malloc(len*sizeof(TCHAR));
1098         len = GetWindowText(hwnd, strval, len);
1099         ret = utf_16to8(strval);
1100         g_free(strval);
1101         return ret;
1102     } else {
1103         return "";
1104     }
1105 }
1106
1107
1108 /* XXX - Copied from "filter-util.c" in the wireshark-win32 branch */
1109 /* XXX - The only reason for the "filter_text" parameter is to be able to feed
1110  * in the "real" filter string in the case of a CBN_SELCHANGE notification message.
1111  */
1112 void
1113 filter_tb_syntax_check(HWND hwnd, TCHAR *filter_text) {
1114     TCHAR     *strval = NULL;
1115     gint       len;
1116     dfilter_t *dfp;
1117
1118     /* If filter_text is non-NULL, use it.  Otherwise, grab the text from
1119      * the window */
1120     if (filter_text) {
1121         len = (lstrlen(filter_text) + 1) * sizeof(TCHAR);
1122         strval = g_malloc(len);
1123         memcpy(strval, filter_text, len);
1124     } else {
1125         len = GetWindowTextLength(hwnd);
1126         if (len > 0) {
1127             len++;
1128             strval = g_malloc(len*sizeof(TCHAR));
1129             len = GetWindowText(hwnd, strval, len);
1130         }
1131     }
1132
1133     if (len == 0) {
1134         /* Default window background */
1135         SendMessage(hwnd, EM_SETBKGNDCOLOR, (WPARAM) 1, COLOR_WINDOW);
1136         return;
1137     } else if (dfilter_compile(utf_16to8(strval), &dfp)) { /* colorize filter string entry */
1138         if (dfp != NULL)
1139             dfilter_free(dfp);
1140         /* Valid (light green) */
1141         SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, 0x00afffaf);
1142     } else {
1143         /* Invalid (light red) */
1144         SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, 0x00afafff);
1145     }
1146
1147     if (strval) g_free(strval);
1148 }
1149
1150
1151 #if (_MSC_VER <= 1200)
1152 static UINT CALLBACK
1153 #else
1154 static UINT_PTR CALLBACK
1155 #endif
1156 open_file_hook_proc(HWND of_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1157     HWND      cur_ctrl, parent;
1158     OFNOTIFY *notify = (OFNOTIFY *) l_param;
1159     TCHAR     sel_name[MAX_PATH];
1160
1161     switch(msg) {
1162         case WM_INITDIALOG:
1163             /* Retain the filter text, and fill it in. */
1164             if(dfilter_open_str != NULL) {
1165                 cur_ctrl = GetDlgItem(of_hwnd, EWFD_FILTER_EDIT);
1166                 SetWindowText(cur_ctrl, utf_8to16(dfilter_open_str));
1167             }
1168
1169             /* Fill in our resolution values */
1170             cur_ctrl = GetDlgItem(of_hwnd, EWFD_MAC_NR_CB);
1171             SendMessage(cur_ctrl, BM_SETCHECK, g_resolv_flags & RESOLV_MAC, 0);
1172             cur_ctrl = GetDlgItem(of_hwnd, EWFD_NET_NR_CB);
1173             SendMessage(cur_ctrl, BM_SETCHECK, g_resolv_flags & RESOLV_NETWORK, 0);
1174             cur_ctrl = GetDlgItem(of_hwnd, EWFD_TRANS_NR_CB);
1175             SendMessage(cur_ctrl, BM_SETCHECK, g_resolv_flags & RESOLV_TRANSPORT, 0);
1176
1177             preview_set_filename(of_hwnd, NULL);
1178             break;
1179         case WM_NOTIFY:
1180             switch (notify->hdr.code) {
1181                 case CDN_FILEOK:
1182                     /* Fetch the read filter */
1183                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_FILTER_EDIT);
1184                     dfilter_open_str = filter_tb_get(cur_ctrl);
1185
1186                     /* Fetch our resolution values */
1187                     g_resolv_flags = prefs.name_resolve & RESOLV_CONCURRENT;
1188                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_MAC_NR_CB);
1189                     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1190                         g_resolv_flags |= RESOLV_MAC;
1191                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_NET_NR_CB);
1192                     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1193                         g_resolv_flags |= RESOLV_NETWORK;
1194                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_TRANS_NR_CB);
1195                     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1196                         g_resolv_flags |= RESOLV_TRANSPORT;
1197                     break;
1198                 case CDN_SELCHANGE:
1199                     /* This _almost_ works correctly. We need to handle directory
1200                        selections, etc. */
1201                     parent = GetParent(of_hwnd);
1202                     CommDlg_OpenSave_GetSpec(parent, sel_name, MAX_PATH);
1203                     preview_set_filename(of_hwnd, utf_16to8(sel_name));
1204                     break;
1205                 case CDN_HELP:
1206                     topic_cb(NULL, HELP_OPEN_WIN32_DIALOG);
1207                     break;
1208                 default:
1209                     break;
1210             }
1211             break;
1212         case WM_COMMAND:
1213             cur_ctrl = (HWND) l_param;
1214             switch(w_param) {
1215                 case (EN_UPDATE << 16) | EWFD_FILTER_EDIT:
1216                     filter_tb_syntax_check(cur_ctrl, NULL);
1217                     break;
1218                     /*
1219                      * If we ever figure out a way to integrate the Windows
1220                      * and GTK+ event loops (or make a native filter dialog),
1221                      * we can re-enable the "Filter" button.
1222                      */
1223                     /*
1224                 case EWFD_FILTER_BTN:
1225                     break;
1226                      */
1227                 default:
1228                     break;
1229             }
1230             break;
1231         default:
1232             break;
1233     }
1234     return 0;
1235 }
1236
1237 /* XXX - Copied verbatim from gtk/capture_file_dlg.c.  Perhaps it
1238  * should be in wiretap instead?
1239  */
1240
1241 static gboolean
1242 can_save_with_wiretap(int ft)
1243 {
1244     /* To save a file with Wiretap, Wiretap has to handle that format,
1245      and its code to handle that format must be able to write a file
1246      with this file's encapsulation type. */
1247     return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
1248 }
1249
1250 /* Generate a list of the file types we can save this file as.
1251
1252    "filetype" is the type it has now.
1253
1254    "encap" is the encapsulation for its packets (which could be
1255    "unknown" or "per-packet").
1256
1257    "filtered" is TRUE if we're to save only the packets that passed
1258    the display filter (in which case we have to save it using Wiretap)
1259    and FALSE if we're to save the entire file (in which case, if we're
1260    saving it in the type it has already, we can just copy it).
1261
1262    The same applies for sel_curr, sel_all, sel_m_only, sel_m_range and sel_man_range
1263 */
1264
1265 static int
1266 file_type_from_list_index(gboolean save, int index) {
1267     int   ft;
1268     int curr_index;
1269
1270     /* Check all file types. */
1271     curr_index = 0;
1272     for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1273         if (save && (!packet_range_process_all(&range) || ft != cfile.cd_t)) {
1274             /* not all unfiltered packets or a different file type.  We have to use Wiretap. */
1275             if (!can_save_with_wiretap(ft))
1276                 continue;       /* We can't. */
1277         }
1278
1279         /* OK, we can write it out in this type. */
1280         if(wtap_file_type_string(ft) == NULL) {
1281             continue;
1282         }
1283
1284         curr_index++;
1285         if(curr_index == index) {
1286             return ft;
1287         }
1288     }
1289
1290     return -1;
1291 }
1292
1293
1294 static TCHAR *
1295 build_file_type_list(gboolean save, int *item_to_select) {
1296     int   ft;
1297     guint index;
1298     GString* str = g_string_new("");
1299     TCHAR *str16;
1300     GArray* sa = g_array_new(FALSE /*zero_terminated*/, FALSE /*clear_*/,2 /*element_size*/);
1301     guint16 zero = 0;
1302
1303
1304     /* Default to the first supported file type, if the file's current
1305        type isn't supported. */
1306     if(item_to_select) {
1307         if(save) {
1308             *item_to_select = FILE_SAVE_DEFAULT;
1309         } else {
1310             *item_to_select = FILE_OPEN_DEFAULT;
1311         }
1312     }
1313
1314     /* append the "All Files" entry */
1315     if (!save) {
1316         str16 = utf_8to16("All Files (*.*)");
1317         sa = g_array_append_vals(sa, str16, (guint) strlen("All Files (*.*)"));
1318         sa = g_array_append_val(sa, zero);
1319         str16 = utf_8to16("*.*");
1320         sa = g_array_append_vals(sa, str16, (guint) strlen("*.*"));
1321         sa = g_array_append_val(sa, zero);
1322     }
1323
1324     /* Check all file types. */
1325     index = 1;  /* the index is one based! */
1326     for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1327         if (save && (!packet_range_process_all(&range) || ft != cfile.cd_t)) {
1328             /* not all unfiltered packets or a different file type.  We have to use Wiretap. */
1329             if (!can_save_with_wiretap(ft))
1330                 continue;       /* We can't. */
1331         }
1332
1333         /* OK, we can write it out in this type. */
1334         if(wtap_file_type_string(ft) != NULL) {
1335             g_string_printf(str, "%s (%s)", wtap_file_type_string(ft), wtap_file_extensions_string(ft));
1336         } else {
1337             continue;
1338         }
1339         str16 = utf_8to16(str->str);
1340         sa = g_array_append_vals(sa, str16, (guint) strlen(str->str));
1341         sa = g_array_append_val(sa, zero);
1342
1343         g_string_printf(str, "%s", wtap_file_extensions_string(ft));
1344         str16 = utf_8to16(str->str);
1345         sa = g_array_append_vals(sa, str16, (guint) strlen(str->str));
1346         sa = g_array_append_val(sa, zero);
1347
1348         if (ft == cfile.cd_t && item_to_select != NULL) {
1349             /* Default to the same format as the file, if it's supported. */
1350             *item_to_select = index;
1351         }
1352         index++;
1353     }
1354
1355     /* terminate the array */
1356     sa = g_array_append_val(sa, zero);
1357
1358     return (TCHAR *) g_array_free(sa, FALSE /*free_segment*/);
1359 }
1360
1361
1362 #if 0
1363 static void
1364 build_file_format_list(HWND sf_hwnd) {
1365     HWND  format_cb;
1366     int   ft;
1367     guint index;
1368     guint item_to_select;
1369     gchar *s;
1370
1371     /* Default to the first supported file type, if the file's current
1372        type isn't supported. */
1373     item_to_select = 0;
1374
1375     format_cb = GetDlgItem(sf_hwnd, EWFD_FILE_TYPE_COMBO);
1376     SendMessage(format_cb, CB_RESETCONTENT, 0, 0);
1377
1378     /* Check all file types. */
1379     index = 0;
1380     for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1381         if (!packet_range_process_all(&range) || ft != cfile.cd_t) {
1382             /* not all unfiltered packets or a different file type.  We have to use Wiretap. */
1383             if (!can_save_with_wiretap(ft))
1384                 continue;       /* We can't. */
1385         }
1386
1387         /* OK, we can write it out in this type. */
1388         if(wtap_file_extensions_string(ft) != NULL) {
1389             s = g_strdup_printf("%s (%s)", wtap_file_type_string(ft), wtap_file_extensions_string(ft));
1390         } else {
1391             s = g_strdup_printf("%s (*.*)", wtap_file_type_string(ft));
1392         }
1393         SendMessage(format_cb, CB_ADDSTRING, 0, (LPARAM) utf_8to16(s));
1394         g_free(s);
1395         SendMessage(format_cb, CB_SETITEMDATA, (LPARAM) index, (WPARAM) ft);
1396         if (ft == filetype) {
1397             /* Default to the same format as the file, if it's supported. */
1398             item_to_select = index;
1399         }
1400         index++;
1401     }
1402
1403     SendMessage(format_cb, CB_SETCURSEL, (WPARAM) item_to_select, 0);
1404 }
1405 #endif
1406
1407 #define RANGE_TEXT_MAX 128
1408 #if (_MSC_VER <= 1200)
1409 static UINT CALLBACK
1410 #else
1411 static UINT_PTR CALLBACK
1412 #endif
1413 save_as_file_hook_proc(HWND sf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1414     HWND           cur_ctrl;
1415     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
1416     /*int            new_filetype, index;*/
1417
1418     switch(msg) {
1419         case WM_INITDIALOG:
1420             g_sf_hwnd = sf_hwnd;
1421
1422             /* Default to saving all packets, in the file's current format. */
1423             filetype = cfile.cd_t;
1424
1425             /* init the packet range */
1426             packet_range_init(&range);
1427
1428             /* Fill in the file format list */
1429             /*build_file_format_list(sf_hwnd);*/
1430
1431             range_handle_wm_initdialog(sf_hwnd, &range);
1432
1433             break;
1434         case WM_COMMAND:
1435             cur_ctrl = (HWND) l_param;
1436
1437             switch (w_param) {
1438 #if 0
1439                 case (CBN_SELCHANGE << 16) | EWFD_FILE_TYPE_COMBO:
1440                     index = SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0);
1441                     if (index != CB_ERR) {
1442                         new_filetype = SendMessage(cur_ctrl, CB_GETITEMDATA, (WPARAM) index, 0);
1443                         if (new_filetype != CB_ERR) {
1444                             if (filetype != new_filetype) {
1445                                 if (can_save_with_wiretap(new_filetype)) {
1446                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_CAPTURED_BTN);
1447                                     EnableWindow(cur_ctrl, TRUE);
1448                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_DISPLAYED_BTN);
1449                                     EnableWindow(cur_ctrl, TRUE);
1450                                 } else {
1451                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_CAPTURED_BTN);
1452                                     SendMessage(cur_ctrl, BM_SETCHECK, 0, 0);
1453                                     EnableWindow(cur_ctrl, FALSE);
1454                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_DISPLAYED_BTN);
1455                                     EnableWindow(cur_ctrl, FALSE);
1456                                 }
1457                                 filetype = new_filetype;
1458                             }
1459                         }
1460                     }
1461                     break;
1462 #endif
1463                 default:
1464                     range_handle_wm_command(sf_hwnd, cur_ctrl, w_param, &range);
1465                     break;
1466             }
1467             break;
1468         case WM_NOTIFY:
1469             switch (notify->hdr.code) {
1470                 case CDN_HELP:
1471                     topic_cb(NULL, HELP_SAVE_WIN32_DIALOG);
1472                     break;
1473                 default:
1474                     break;
1475             }
1476             break;
1477         default:
1478             break;
1479     }
1480     return 0;
1481 }
1482
1483
1484
1485 /* For each range static control, fill in its value and enable/disable it. */
1486 static void
1487 range_update_dynamics(HWND dlg_hwnd, packet_range_t *range) {
1488     HWND     cur_ctrl;
1489     gboolean filtered_active = FALSE;
1490     TCHAR    static_val[100];
1491     gint     selected_num;
1492
1493     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_DISPLAYED_BTN);
1494     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1495         filtered_active = TRUE;
1496
1497     /* RANGE_SELECT_ALL */
1498     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_CAP);
1499     EnableWindow(cur_ctrl, !filtered_active);
1500     _snwprintf(static_val, sizeof(static_val), _T("%u"), cfile.count);
1501     SetWindowText(cur_ctrl, static_val);
1502
1503     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_DISP);
1504     EnableWindow(cur_ctrl, filtered_active);
1505     _snwprintf(static_val, sizeof(static_val), _T("%u"), range->displayed_cnt);
1506     SetWindowText(cur_ctrl, static_val);
1507
1508     /* RANGE_SELECT_CURR */
1509     selected_num = (cfile.current_frame) ? cfile.current_frame->num : 0;
1510     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_CAP);
1511     EnableWindow(cur_ctrl, selected_num && !filtered_active);
1512     _snwprintf(static_val, sizeof(static_val), _T("%u"), selected_num ? 1 : 0);
1513     SetWindowText(cur_ctrl, static_val);
1514
1515     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_DISP);
1516     EnableWindow(cur_ctrl, selected_num && filtered_active);
1517     _snwprintf(static_val, sizeof(static_val), _T("%u"), selected_num ? 1 : 0);
1518     SetWindowText(cur_ctrl, static_val);
1519
1520     /* RANGE_SELECT_MARKED */
1521     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_BTN);
1522     EnableWindow(cur_ctrl, cfile.marked_count);
1523
1524     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_CAP);
1525     EnableWindow(cur_ctrl, cfile.marked_count && !filtered_active);
1526     _snwprintf(static_val, sizeof(static_val), _T("%u"), cfile.marked_count);
1527     SetWindowText(cur_ctrl, static_val);
1528
1529     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_DISP);
1530     EnableWindow(cur_ctrl, cfile.marked_count && filtered_active);
1531     _snwprintf(static_val, sizeof(static_val), _T("%u"), range->displayed_marked_cnt);
1532     SetWindowText(cur_ctrl, static_val);
1533
1534     /* RANGE_SELECT_MARKED_RANGE */
1535     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_BTN);
1536     EnableWindow(cur_ctrl, range->mark_range_cnt);
1537
1538     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_CAP);
1539     EnableWindow(cur_ctrl, range->mark_range_cnt && !filtered_active);
1540     _snwprintf(static_val, sizeof(static_val), _T("%u"), range->mark_range_cnt);
1541     SetWindowText(cur_ctrl, static_val);
1542
1543     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_DISP);
1544     EnableWindow(cur_ctrl, range->displayed_mark_range_cnt && filtered_active);
1545     _snwprintf(static_val, sizeof(static_val), _T("%u"), range->displayed_mark_range_cnt);
1546     SetWindowText(cur_ctrl, static_val);
1547
1548     /* RANGE_SELECT_USER */
1549     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_CAP);
1550     EnableWindow(cur_ctrl, !filtered_active);
1551     _snwprintf(static_val, sizeof(static_val), _T("%u"), range->user_range_cnt);
1552     SetWindowText(cur_ctrl, static_val);
1553
1554     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_DISP);
1555     EnableWindow(cur_ctrl, filtered_active);
1556     _snwprintf(static_val, sizeof(static_val), _T("%u"), range->displayed_user_range_cnt);
1557     SetWindowText(cur_ctrl, static_val);
1558 }
1559
1560 static void
1561 range_handle_wm_initdialog(HWND dlg_hwnd, packet_range_t *range) {
1562     HWND cur_ctrl;
1563
1564     /* Set the appropriate captured/displayed radio */
1565     if (range->process_filtered)
1566         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_DISPLAYED_BTN);
1567     else
1568         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_CAPTURED_BTN);
1569     SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
1570
1571     /* dynamic values in the range frame */
1572     range_update_dynamics(dlg_hwnd, range);
1573
1574     /* Set the appropriate range radio */
1575     switch(range->process) {
1576         case(range_process_all):
1577             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_BTN);
1578             break;
1579         case(range_process_selected):
1580             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_BTN);
1581             break;
1582         case(range_process_marked):
1583             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_BTN);
1584             break;
1585         case(range_process_marked_range):
1586             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_BTN);
1587             break;
1588         case(range_process_user_range):
1589             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_BTN);
1590             break;
1591         default:
1592             g_assert_not_reached();
1593     }
1594     SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
1595 }
1596
1597 static void
1598 range_handle_wm_command(HWND dlg_hwnd, HWND ctrl, WPARAM w_param, packet_range_t *range) {
1599     HWND  cur_ctrl;
1600     TCHAR range_text[RANGE_TEXT_MAX];
1601
1602     switch(w_param) {
1603         case (BN_CLICKED << 16) | EWFD_CAPTURED_BTN:
1604         case (BN_CLICKED << 16) | EWFD_DISPLAYED_BTN:
1605             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_CAPTURED_BTN);
1606             if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1607                 range->process_filtered = FALSE;
1608             else
1609                 range->process_filtered = TRUE;
1610             range_update_dynamics(dlg_hwnd, range);
1611             break;
1612         case (BN_CLICKED << 16) | EWFD_ALL_PKTS_BTN:
1613             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1614                 range->process = range_process_all;
1615                 range_update_dynamics(dlg_hwnd, range);
1616             }
1617             break;
1618         case (BN_CLICKED << 16) | EWFD_SEL_PKT_BTN:
1619             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1620                 range->process = range_process_selected;
1621                 range_update_dynamics(dlg_hwnd, range);
1622             }
1623             break;
1624         case (BN_CLICKED << 16) | EWFD_MARKED_BTN:
1625             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1626                 range->process = range_process_marked;
1627                 range_update_dynamics(dlg_hwnd, range);
1628             }
1629             break;
1630         case (BN_CLICKED << 16) | EWFD_FIRST_LAST_BTN:
1631             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1632                 range->process = range_process_marked_range;
1633                 range_update_dynamics(dlg_hwnd, range);
1634             }
1635             break;
1636         case (BN_CLICKED << 16) | EWFD_RANGE_BTN:
1637             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1638                 range->process = range_process_user_range;
1639                 range_update_dynamics(dlg_hwnd, range);
1640                 cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
1641                 SetFocus(cur_ctrl);
1642             }
1643             break;
1644         case (EN_SETFOCUS << 16) | EWFD_RANGE_EDIT:
1645             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_BTN);
1646             SendMessage(cur_ctrl, BM_CLICK, 0, 0);
1647             break;
1648         case (EN_CHANGE << 16) | EWFD_RANGE_EDIT:
1649             SendMessage(ctrl, WM_GETTEXT, (WPARAM) RANGE_TEXT_MAX, (LPARAM) range_text);
1650             packet_range_convert_str(range, utf_16to8(range_text));
1651             range_update_dynamics(dlg_hwnd, range);
1652             break;
1653     }
1654 }
1655
1656 #if (_MSC_VER <= 1200)
1657 static UINT CALLBACK
1658 #else
1659 static UINT_PTR CALLBACK
1660 #endif
1661 merge_file_hook_proc(HWND mf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1662     HWND      cur_ctrl, parent;
1663     OFNOTIFY *notify = (OFNOTIFY *) l_param;
1664     TCHAR     sel_name[MAX_PATH];
1665
1666     switch(msg) {
1667         case WM_INITDIALOG:
1668             /* Retain the filter text, and fill it in. */
1669             if(dfilter_merge_str != NULL) {
1670                 cur_ctrl = GetDlgItem(mf_hwnd, EWFD_FILTER_EDIT);
1671                 SetWindowText(cur_ctrl, utf_8to16(dfilter_merge_str));
1672             }
1673
1674             /* Append by default */
1675             cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_PREPEND_BTN);
1676             SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
1677             merge_action = merge_append;
1678
1679             preview_set_filename(mf_hwnd, NULL);
1680             break;
1681         case WM_NOTIFY:
1682             switch (notify->hdr.code) {
1683                 case CDN_FILEOK:
1684                     /* Fetch the read filter */
1685                     cur_ctrl = GetDlgItem(mf_hwnd, EWFD_FILTER_EDIT);
1686                     dfilter_merge_str = filter_tb_get(cur_ctrl);
1687
1688                     cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_CHRONO_BTN);
1689                     if(SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1690                         merge_action = merge_chrono;
1691                     } else {
1692                         cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_PREPEND_BTN);
1693                         if(SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1694                             merge_action = merge_prepend;
1695                         }
1696                     }
1697
1698                     break;
1699                 case CDN_SELCHANGE:
1700                     /* This _almost_ works correctly.  We need to handle directory
1701                        selections, etc. */
1702                     parent = GetParent(mf_hwnd);
1703                     CommDlg_OpenSave_GetSpec(parent, sel_name, MAX_PATH);
1704                     preview_set_filename(mf_hwnd, utf_16to8(sel_name));
1705                     break;
1706                 case CDN_HELP:
1707                     topic_cb(NULL, HELP_MERGE_WIN32_DIALOG);
1708                     break;
1709                 default:
1710                     break;
1711             }
1712             break;
1713         case WM_COMMAND:
1714             cur_ctrl = (HWND) l_param;
1715             switch(w_param) {
1716                 case (EN_UPDATE << 16) | EWFD_FILTER_EDIT:
1717                     filter_tb_syntax_check(cur_ctrl, NULL);
1718                     break;
1719                 default:
1720                     break;
1721             }
1722             break;
1723         default:
1724             break;
1725     }
1726     return 0;
1727 }
1728
1729
1730 #if (_MSC_VER <= 1200)
1731 static UINT CALLBACK
1732 #else
1733 static UINT_PTR CALLBACK
1734 #endif
1735 export_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1736     HWND           cur_ctrl;
1737     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
1738     gboolean       pkt_fmt_enable;
1739     int            i, index;
1740
1741     switch(msg) {
1742         case WM_INITDIALOG:
1743             /* init the printing range */
1744             packet_range_init(&print_args.range);
1745             range_handle_wm_initdialog(ef_hwnd, &print_args.range);
1746             format_handle_wm_initdialog(ef_hwnd, &print_args);
1747
1748             break;
1749         case WM_COMMAND:
1750             cur_ctrl = (HWND) l_param;
1751             switch (w_param) {
1752                 case (CBN_SELCHANGE << 16) | EWFD_PKT_DETAIL_COMBO:
1753                 default:
1754                     range_handle_wm_command(ef_hwnd, cur_ctrl, w_param, &print_args.range);
1755                     print_update_dynamic(ef_hwnd, &print_args);
1756                     break;
1757             }
1758             break;
1759         case WM_NOTIFY:
1760             switch (notify->hdr.code) {
1761                 case CDN_FILEOK:
1762                     break;
1763                 case CDN_TYPECHANGE:
1764                     index = notify->lpOFN->nFilterIndex;
1765
1766                     if (index == 2)     /* PostScript */
1767                         print_args.format = PR_FMT_TEXT;
1768                     else
1769                         print_args.format = PR_FMT_PS;
1770                     if (index == 3 || index == 4 || index == 5 || index == 6)
1771                         pkt_fmt_enable = FALSE;
1772                     else
1773                         pkt_fmt_enable = TRUE;
1774                     for (i = EWFD_PKT_FORMAT_GB; i <= EWFD_PKT_NEW_PAGE_CB; i++) {
1775                         cur_ctrl = GetDlgItem(ef_hwnd, i);
1776                         EnableWindow(cur_ctrl, pkt_fmt_enable);
1777                     }
1778                     break;
1779                 case CDN_HELP:
1780                     topic_cb(NULL, HELP_EXPORT_FILE_WIN32_DIALOG);
1781                     break;
1782                 default:
1783                     break;
1784             }
1785             break;
1786         default:
1787             break;
1788     }
1789     return 0;
1790 }
1791
1792 #if (_MSC_VER <= 1200)
1793 static UINT CALLBACK
1794 #else
1795 static UINT_PTR CALLBACK
1796 #endif
1797 export_raw_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1798     HWND          cur_ctrl;
1799     OPENFILENAME *ofnp = (OPENFILENAME *) l_param;
1800     TCHAR         raw_msg[100];
1801     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
1802
1803     switch(msg) {
1804         case WM_INITDIALOG:
1805             _snwprintf(raw_msg, sizeof(raw_msg), _T("%d byte%s of raw binary data will be written"),
1806                     ofnp->lCustData, plurality(ofnp->lCustData, "", "s"));
1807             cur_ctrl = GetDlgItem(ef_hwnd, EWFD_EXPORTRAW_ST);
1808             SetWindowText(cur_ctrl, raw_msg);
1809             break;
1810         case WM_NOTIFY:
1811             switch (notify->hdr.code) {
1812                 case CDN_HELP:
1813                     topic_cb(NULL, HELP_EXPORT_BYTES_WIN32_DIALOG);
1814                     break;
1815                 default:
1816                     break;
1817             }
1818         default:
1819             break;
1820     }
1821     return 0;
1822 }
1823
1824 /*
1825  * Editor modelines
1826  *
1827  * Local Variables:
1828  * c-basic-offset: 4
1829  * tab-width: 8
1830  * indent-tabs-mode: nil
1831  * End:
1832  *
1833  * ex: set shiftwidth=4 tabstop=8 expandtab
1834  * :indentSize=4:tabSize=8:noTabs=true:
1835  */
1836