Detect clang and llvm-gcc.
[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, FALSE)) {
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, FALSE)) {
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     gint64      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         utf_8to16_snprintf(string_buff, PREVIEW_STR_MAX, "%" G_GINT64_FORMAT " 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     guint32  ignored_cnt = 0, displayed_ignored_cnt = 0;
1493
1494     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_DISPLAYED_BTN);
1495     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1496         filtered_active = TRUE;
1497
1498     /* RANGE_SELECT_ALL */
1499     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_CAP);
1500     EnableWindow(cur_ctrl, !filtered_active);
1501     if (range->remove_ignored) {
1502         _snwprintf(static_val, sizeof(static_val), _T("%u"), cfile.count - range->ignored_cnt);
1503     } else {
1504         _snwprintf(static_val, sizeof(static_val), _T("%u"), cfile.count);
1505     }
1506     SetWindowText(cur_ctrl, static_val);
1507
1508     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_DISP);
1509     EnableWindow(cur_ctrl, filtered_active);
1510     if (range->remove_ignored) {
1511         _snwprintf(static_val, sizeof(static_val), _T("%u"), range->displayed_cnt - range->displayed_ignored_cnt);
1512     } else {
1513         _snwprintf(static_val, sizeof(static_val), _T("%u"), range->displayed_cnt);
1514     }
1515     SetWindowText(cur_ctrl, static_val);
1516
1517     /* RANGE_SELECT_CURR */
1518     selected_num = (cfile.current_frame) ? cfile.current_frame->num : 0;
1519     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_CAP);
1520     EnableWindow(cur_ctrl, selected_num && !filtered_active);
1521     if (range->remove_ignored && cfile.current_frame && cfile.current_frame->flags.ignored) {
1522         _snwprintf(static_val, sizeof(static_val), _T("0"));
1523     } else {
1524         _snwprintf(static_val, sizeof(static_val), _T("%u"), selected_num ? 1 : 0);
1525     }
1526     SetWindowText(cur_ctrl, static_val);
1527
1528     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_DISP);
1529     EnableWindow(cur_ctrl, selected_num && filtered_active);
1530     if (range->remove_ignored && cfile.current_frame && cfile.current_frame->flags.ignored) {
1531         _snwprintf(static_val, sizeof(static_val), _T("0"));
1532     } else {
1533         _snwprintf(static_val, sizeof(static_val), _T("%u"), selected_num ? 1 : 0);
1534     }
1535     SetWindowText(cur_ctrl, static_val);
1536
1537     /* RANGE_SELECT_MARKED */
1538     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_BTN);
1539     EnableWindow(cur_ctrl, cfile.marked_count);
1540
1541     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_CAP);
1542     EnableWindow(cur_ctrl, cfile.marked_count && !filtered_active);
1543     if (range->remove_ignored) {
1544         _snwprintf(static_val, sizeof(static_val), _T("%u"), cfile.marked_count - range->ignored_marked_cnt);
1545     } else {
1546         _snwprintf(static_val, sizeof(static_val), _T("%u"), cfile.marked_count);
1547     }
1548     SetWindowText(cur_ctrl, static_val);
1549
1550     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_DISP);
1551     EnableWindow(cur_ctrl, cfile.marked_count && filtered_active);
1552     if (range->remove_ignored) {
1553         _snwprintf(static_val, sizeof(static_val), _T("%u"), range->displayed_marked_cnt - range->displayed_ignored_marked_cnt);
1554     } else {
1555         _snwprintf(static_val, sizeof(static_val), _T("%u"), range->displayed_marked_cnt);
1556     }
1557     SetWindowText(cur_ctrl, static_val);
1558
1559     /* RANGE_SELECT_MARKED_RANGE */
1560     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_BTN);
1561     EnableWindow(cur_ctrl, range->mark_range_cnt);
1562
1563     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_CAP);
1564     EnableWindow(cur_ctrl, range->mark_range_cnt && !filtered_active);
1565     if (range->remove_ignored) {
1566         _snwprintf(static_val, sizeof(static_val), _T("%u"), range->mark_range_cnt - range->ignored_mark_range_cnt);
1567     } else {
1568         _snwprintf(static_val, sizeof(static_val), _T("%u"), range->mark_range_cnt);
1569     }
1570     SetWindowText(cur_ctrl, static_val);
1571
1572     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_DISP);
1573     EnableWindow(cur_ctrl, range->displayed_mark_range_cnt && filtered_active);
1574     if (range->remove_ignored) {
1575         _snwprintf(static_val, sizeof(static_val), _T("%u"), range->displayed_mark_range_cnt - range->displayed_ignored_mark_range_cnt);
1576     } else {
1577         _snwprintf(static_val, sizeof(static_val), _T("%u"), range->displayed_mark_range_cnt);
1578     }
1579     SetWindowText(cur_ctrl, static_val);
1580
1581     /* RANGE_SELECT_USER */
1582     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_CAP);
1583     EnableWindow(cur_ctrl, !filtered_active);
1584     if (range->remove_ignored) {
1585         _snwprintf(static_val, sizeof(static_val), _T("%u"), range->user_range_cnt - range->ignored_user_range_cnt);
1586     } else {
1587         _snwprintf(static_val, sizeof(static_val), _T("%u"), range->user_range_cnt);
1588     }
1589     SetWindowText(cur_ctrl, static_val);
1590
1591     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_DISP);
1592     EnableWindow(cur_ctrl, filtered_active);
1593     if (range->remove_ignored) {
1594         _snwprintf(static_val, sizeof(static_val), _T("%u"), range->displayed_user_range_cnt - range->displayed_ignored_user_range_cnt);
1595     } else {
1596         _snwprintf(static_val, sizeof(static_val), _T("%u"), range->displayed_user_range_cnt);
1597     }
1598     SetWindowText(cur_ctrl, static_val);
1599
1600     /* RANGE_REMOVE_IGNORED_PACKETS */
1601     switch(range->process) {
1602         case(range_process_all):
1603             ignored_cnt = range->ignored_cnt;
1604             displayed_ignored_cnt = range->displayed_ignored_cnt;
1605             break;
1606         case(range_process_selected):
1607             ignored_cnt = (cfile.current_frame && cfile.current_frame->flags.ignored) ? 1 : 0;
1608             displayed_ignored_cnt = ignored_cnt;
1609             break;
1610         case(range_process_marked):
1611             ignored_cnt = range->ignored_marked_cnt;
1612             displayed_ignored_cnt = range->displayed_ignored_marked_cnt;
1613             break;
1614         case(range_process_marked_range):
1615             ignored_cnt = range->ignored_mark_range_cnt;
1616             displayed_ignored_cnt = range->displayed_ignored_mark_range_cnt;
1617             break;
1618         case(range_process_user_range):
1619             ignored_cnt = range->ignored_user_range_cnt;
1620             displayed_ignored_cnt = range->displayed_ignored_user_range_cnt;
1621             break;
1622         default:
1623             g_assert_not_reached();
1624     }
1625
1626     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_REMOVE_IGN_CB);
1627     EnableWindow(cur_ctrl, ignored_cnt);
1628
1629     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_IGNORED_CAP);
1630     EnableWindow(cur_ctrl, ignored_cnt && !filtered_active);
1631     _snwprintf(static_val, sizeof(static_val), _T("%u"), ignored_cnt);
1632     SetWindowText(cur_ctrl, static_val);
1633
1634     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_IGNORED_DISP);
1635     EnableWindow(cur_ctrl, displayed_ignored_cnt && filtered_active);
1636     _snwprintf(static_val, sizeof(static_val), _T("%u"), displayed_ignored_cnt);
1637     SetWindowText(cur_ctrl, static_val);
1638 }
1639
1640 static void
1641 range_handle_wm_initdialog(HWND dlg_hwnd, packet_range_t *range) {
1642     HWND cur_ctrl;
1643
1644     /* Set the appropriate captured/displayed radio */
1645     if (range->process_filtered)
1646         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_DISPLAYED_BTN);
1647     else
1648         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_CAPTURED_BTN);
1649     SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
1650
1651     /* dynamic values in the range frame */
1652     range_update_dynamics(dlg_hwnd, range);
1653
1654     /* Set the appropriate range radio */
1655     switch(range->process) {
1656         case(range_process_all):
1657             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_BTN);
1658             break;
1659         case(range_process_selected):
1660             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_BTN);
1661             break;
1662         case(range_process_marked):
1663             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_BTN);
1664             break;
1665         case(range_process_marked_range):
1666             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_BTN);
1667             break;
1668         case(range_process_user_range):
1669             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_BTN);
1670             break;
1671         default:
1672             g_assert_not_reached();
1673     }
1674     SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
1675 }
1676
1677 static void
1678 range_handle_wm_command(HWND dlg_hwnd, HWND ctrl, WPARAM w_param, packet_range_t *range) {
1679     HWND  cur_ctrl;
1680     TCHAR range_text[RANGE_TEXT_MAX];
1681
1682     switch(w_param) {
1683         case (BN_CLICKED << 16) | EWFD_CAPTURED_BTN:
1684         case (BN_CLICKED << 16) | EWFD_DISPLAYED_BTN:
1685             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_CAPTURED_BTN);
1686             if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1687                 range->process_filtered = FALSE;
1688             else
1689                 range->process_filtered = TRUE;
1690             range_update_dynamics(dlg_hwnd, range);
1691             break;
1692         case (BN_CLICKED << 16) | EWFD_ALL_PKTS_BTN:
1693             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1694                 range->process = range_process_all;
1695                 range_update_dynamics(dlg_hwnd, range);
1696             }
1697             break;
1698         case (BN_CLICKED << 16) | EWFD_SEL_PKT_BTN:
1699             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1700                 range->process = range_process_selected;
1701                 range_update_dynamics(dlg_hwnd, range);
1702             }
1703             break;
1704         case (BN_CLICKED << 16) | EWFD_MARKED_BTN:
1705             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1706                 range->process = range_process_marked;
1707                 range_update_dynamics(dlg_hwnd, range);
1708             }
1709             break;
1710         case (BN_CLICKED << 16) | EWFD_FIRST_LAST_BTN:
1711             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1712                 range->process = range_process_marked_range;
1713                 range_update_dynamics(dlg_hwnd, range);
1714             }
1715             break;
1716         case (BN_CLICKED << 16) | EWFD_RANGE_BTN:
1717             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1718                 range->process = range_process_user_range;
1719                 range_update_dynamics(dlg_hwnd, range);
1720                 cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
1721                 SetFocus(cur_ctrl);
1722             }
1723             break;
1724         case (EN_SETFOCUS << 16) | EWFD_RANGE_EDIT:
1725             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_BTN);
1726             SendMessage(cur_ctrl, BM_CLICK, 0, 0);
1727             break;
1728         case (EN_CHANGE << 16) | EWFD_RANGE_EDIT:
1729             SendMessage(ctrl, WM_GETTEXT, (WPARAM) RANGE_TEXT_MAX, (LPARAM) range_text);
1730             packet_range_convert_str(range, utf_16to8(range_text));
1731             range_update_dynamics(dlg_hwnd, range);
1732             break;
1733         case (BN_CLICKED << 16) | EWFD_REMOVE_IGN_CB:
1734             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1735                 range->remove_ignored = TRUE;
1736             } else {
1737                 range->remove_ignored = FALSE;
1738             }
1739             range_update_dynamics(dlg_hwnd, range);
1740             break;
1741     }
1742 }
1743
1744 #if (_MSC_VER <= 1200)
1745 static UINT CALLBACK
1746 #else
1747 static UINT_PTR CALLBACK
1748 #endif
1749 merge_file_hook_proc(HWND mf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1750     HWND      cur_ctrl, parent;
1751     OFNOTIFY *notify = (OFNOTIFY *) l_param;
1752     TCHAR     sel_name[MAX_PATH];
1753
1754     switch(msg) {
1755         case WM_INITDIALOG:
1756             /* Retain the filter text, and fill it in. */
1757             if(dfilter_merge_str != NULL) {
1758                 cur_ctrl = GetDlgItem(mf_hwnd, EWFD_FILTER_EDIT);
1759                 SetWindowText(cur_ctrl, utf_8to16(dfilter_merge_str));
1760             }
1761
1762             /* Append by default */
1763             cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_PREPEND_BTN);
1764             SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
1765             merge_action = merge_append;
1766
1767             preview_set_filename(mf_hwnd, NULL);
1768             break;
1769         case WM_NOTIFY:
1770             switch (notify->hdr.code) {
1771                 case CDN_FILEOK:
1772                     /* Fetch the read filter */
1773                     cur_ctrl = GetDlgItem(mf_hwnd, EWFD_FILTER_EDIT);
1774                     dfilter_merge_str = filter_tb_get(cur_ctrl);
1775
1776                     cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_CHRONO_BTN);
1777                     if(SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1778                         merge_action = merge_chrono;
1779                     } else {
1780                         cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_PREPEND_BTN);
1781                         if(SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1782                             merge_action = merge_prepend;
1783                         }
1784                     }
1785
1786                     break;
1787                 case CDN_SELCHANGE:
1788                     /* This _almost_ works correctly.  We need to handle directory
1789                        selections, etc. */
1790                     parent = GetParent(mf_hwnd);
1791                     CommDlg_OpenSave_GetSpec(parent, sel_name, MAX_PATH);
1792                     preview_set_filename(mf_hwnd, utf_16to8(sel_name));
1793                     break;
1794                 case CDN_HELP:
1795                     topic_cb(NULL, HELP_MERGE_WIN32_DIALOG);
1796                     break;
1797                 default:
1798                     break;
1799             }
1800             break;
1801         case WM_COMMAND:
1802             cur_ctrl = (HWND) l_param;
1803             switch(w_param) {
1804                 case (EN_UPDATE << 16) | EWFD_FILTER_EDIT:
1805                     filter_tb_syntax_check(cur_ctrl, NULL);
1806                     break;
1807                 default:
1808                     break;
1809             }
1810             break;
1811         default:
1812             break;
1813     }
1814     return 0;
1815 }
1816
1817
1818 #if (_MSC_VER <= 1200)
1819 static UINT CALLBACK
1820 #else
1821 static UINT_PTR CALLBACK
1822 #endif
1823 export_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1824     HWND           cur_ctrl;
1825     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
1826     gboolean       pkt_fmt_enable;
1827     int            i, index;
1828
1829     switch(msg) {
1830         case WM_INITDIALOG:
1831             /* init the printing range */
1832             packet_range_init(&print_args.range);
1833             range_handle_wm_initdialog(ef_hwnd, &print_args.range);
1834             format_handle_wm_initdialog(ef_hwnd, &print_args);
1835
1836             break;
1837         case WM_COMMAND:
1838             cur_ctrl = (HWND) l_param;
1839             switch (w_param) {
1840                 case (CBN_SELCHANGE << 16) | EWFD_PKT_DETAIL_COMBO:
1841                 default:
1842                     range_handle_wm_command(ef_hwnd, cur_ctrl, w_param, &print_args.range);
1843                     print_update_dynamic(ef_hwnd, &print_args);
1844                     break;
1845             }
1846             break;
1847         case WM_NOTIFY:
1848             switch (notify->hdr.code) {
1849                 case CDN_FILEOK:
1850                     break;
1851                 case CDN_TYPECHANGE:
1852                     index = notify->lpOFN->nFilterIndex;
1853
1854                     if (index == 2)     /* PostScript */
1855                         print_args.format = PR_FMT_TEXT;
1856                     else
1857                         print_args.format = PR_FMT_PS;
1858                     if (index == 3 || index == 4 || index == 5 || index == 6)
1859                         pkt_fmt_enable = FALSE;
1860                     else
1861                         pkt_fmt_enable = TRUE;
1862                     for (i = EWFD_PKT_FORMAT_GB; i <= EWFD_PKT_NEW_PAGE_CB; i++) {
1863                         cur_ctrl = GetDlgItem(ef_hwnd, i);
1864                         EnableWindow(cur_ctrl, pkt_fmt_enable);
1865                     }
1866                     break;
1867                 case CDN_HELP:
1868                     topic_cb(NULL, HELP_EXPORT_FILE_WIN32_DIALOG);
1869                     break;
1870                 default:
1871                     break;
1872             }
1873             break;
1874         default:
1875             break;
1876     }
1877     return 0;
1878 }
1879
1880 #if (_MSC_VER <= 1200)
1881 static UINT CALLBACK
1882 #else
1883 static UINT_PTR CALLBACK
1884 #endif
1885 export_raw_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1886     HWND          cur_ctrl;
1887     OPENFILENAME *ofnp = (OPENFILENAME *) l_param;
1888     TCHAR         raw_msg[100];
1889     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
1890
1891     switch(msg) {
1892         case WM_INITDIALOG:
1893             _snwprintf(raw_msg, sizeof(raw_msg), _T("%d byte%s of raw binary data will be written"),
1894                     ofnp->lCustData, plurality(ofnp->lCustData, "", "s"));
1895             cur_ctrl = GetDlgItem(ef_hwnd, EWFD_EXPORTRAW_ST);
1896             SetWindowText(cur_ctrl, raw_msg);
1897             break;
1898         case WM_NOTIFY:
1899             switch (notify->hdr.code) {
1900                 case CDN_HELP:
1901                     topic_cb(NULL, HELP_EXPORT_BYTES_WIN32_DIALOG);
1902                     break;
1903                 default:
1904                     break;
1905             }
1906         default:
1907             break;
1908     }
1909     return 0;
1910 }
1911
1912 /*
1913  * Editor modelines
1914  *
1915  * Local Variables:
1916  * c-basic-offset: 4
1917  * tab-width: 8
1918  * indent-tabs-mode: nil
1919  * End:
1920  *
1921  * ex: set shiftwidth=4 tabstop=8 expandtab
1922  * :indentSize=4:tabSize=8:noTabs=true:
1923  */
1924