wordpad: Don't quit if the user cancels the save-as dialog when being prompted to...
[wine] / programs / wordpad / wordpad.c
1 /*
2  * Wordpad implementation
3  *
4  * Copyright 2004 by Krzysztof Foltman
5  * Copyright 2007-2008 by Alexander N. Sørnes <alex@thehandofagony.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #define WIN32_LEAN_AND_MEAN
23 #define _WIN32_IE 0x0400
24
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <ctype.h>
28 #include <stdio.h>
29 #include <assert.h>
30
31 #include <windows.h>
32 #include <richedit.h>
33 #include <commctrl.h>
34 #include <commdlg.h>
35 #include <shellapi.h>
36 #include <math.h>
37 #include <errno.h>
38
39 #include "wine/unicode.h"
40 #include "wordpad.h"
41
42 #ifdef NONAMELESSUNION
43 # define U(x)  (x).u
44 # define U2(x) (x).u2
45 # define U3(x) (x).u3
46 #else
47 # define U(x)  (x)
48 # define U2(x) (x)
49 # define U3(x) (x)
50 #endif
51
52 /* use LoadString */
53 static const WCHAR wszAppTitle[] = {'W','i','n','e',' ','W','o','r','d','p','a','d',0};
54
55 static const WCHAR wszMainWndClass[] = {'W','O','R','D','P','A','D','T','O','P',0};
56
57 static const WCHAR stringFormat[] = {'%','2','d','\0'};
58
59 const WCHAR wszPreviewWndClass[] = {'P','r','t','P','r','e','v','i','e','w',0};
60 LRESULT CALLBACK preview_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
61
62 static HWND hMainWnd;
63 static HWND hEditorWnd;
64 static HWND hFindWnd;
65 static HMENU hColorPopupMenu;
66
67 static UINT ID_FINDMSGSTRING;
68
69 static DWORD wordWrap[2];
70 static DWORD barState[2];
71 static WPARAM fileFormat = SF_RTF;
72
73 static WCHAR wszFileName[MAX_PATH];
74 static WCHAR wszFilter[MAX_STRING_LEN*4+6*3+5];
75 static WCHAR wszDefaultFileName[MAX_STRING_LEN];
76 static WCHAR wszSaveChanges[MAX_STRING_LEN];
77 static WCHAR units_cmW[MAX_STRING_LEN];
78 static WCHAR units_inW[MAX_STRING_LEN];
79 static WCHAR units_inchW[MAX_STRING_LEN];
80 static WCHAR units_ptW[MAX_STRING_LEN];
81
82 static LRESULT OnSize( HWND hWnd, WPARAM wParam, LPARAM lParam );
83
84 typedef enum
85 {
86     UNIT_CM,
87     UNIT_INCH,
88     UNIT_PT
89 } UNIT;
90
91 typedef struct
92 {
93     int endPos;
94     BOOL wrapped;
95     WCHAR findBuffer[128];
96 } FINDREPLACE_custom;
97
98 /* Load string resources */
99 static void DoLoadStrings(void)
100 {
101     LPWSTR p = wszFilter;
102     static const WCHAR files_rtf[] = {'*','.','r','t','f','\0'};
103     static const WCHAR files_txt[] = {'*','.','t','x','t','\0'};
104     static const WCHAR files_all[] = {'*','.','*','\0'};
105
106     HINSTANCE hInstance = GetModuleHandleW(0);
107
108     LoadStringW(hInstance, STRING_RICHTEXT_FILES_RTF, p, MAX_STRING_LEN);
109     p += lstrlenW(p) + 1;
110     lstrcpyW(p, files_rtf);
111     p += lstrlenW(p) + 1;
112     LoadStringW(hInstance, STRING_TEXT_FILES_TXT, p, MAX_STRING_LEN);
113     p += lstrlenW(p) + 1;
114     lstrcpyW(p, files_txt);
115     p += lstrlenW(p) + 1;
116     LoadStringW(hInstance, STRING_TEXT_FILES_UNICODE_TXT, p, MAX_STRING_LEN);
117     p += lstrlenW(p) + 1;
118     lstrcpyW(p, files_txt);
119     p += lstrlenW(p) + 1;
120     LoadStringW(hInstance, STRING_ALL_FILES, p, MAX_STRING_LEN);
121     p += lstrlenW(p) + 1;
122     lstrcpyW(p, files_all);
123     p += lstrlenW(p) + 1;
124     *p = '\0';
125
126     p = wszDefaultFileName;
127     LoadStringW(hInstance, STRING_DEFAULT_FILENAME, p, MAX_STRING_LEN);
128
129     p = wszSaveChanges;
130     LoadStringW(hInstance, STRING_PROMPT_SAVE_CHANGES, p, MAX_STRING_LEN);
131
132     LoadStringW(hInstance, STRING_UNITS_CM, units_cmW, MAX_STRING_LEN);
133     LoadStringW(hInstance, STRING_UNITS_IN, units_inW, MAX_STRING_LEN);
134     LoadStringW(hInstance, STRING_UNITS_INCH, units_inchW, MAX_STRING_LEN);
135     LoadStringW(hInstance, STRING_UNITS_PT, units_ptW, MAX_STRING_LEN);
136 }
137
138 /* Show a message box with resource strings */
139 static int MessageBoxWithResStringW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
140 {
141     MSGBOXPARAMSW params;
142
143     params.cbSize             = sizeof(params);
144     params.hwndOwner          = hWnd;
145     params.hInstance          = GetModuleHandleW(0);
146     params.lpszText           = lpText;
147     params.lpszCaption        = lpCaption;
148     params.dwStyle            = uType;
149     params.lpszIcon           = NULL;
150     params.dwContextHelpId    = 0;
151     params.lpfnMsgBoxCallback = NULL;
152     params.dwLanguageId       = 0;
153     return MessageBoxIndirectW(&params);
154 }
155
156
157 static void AddButton(HWND hwndToolBar, int nImage, int nCommand)
158 {
159     TBBUTTON button;
160
161     ZeroMemory(&button, sizeof(button));
162     button.iBitmap = nImage;
163     button.idCommand = nCommand;
164     button.fsState = TBSTATE_ENABLED;
165     button.fsStyle = BTNS_BUTTON;
166     button.dwData = 0;
167     button.iString = -1;
168     SendMessageW(hwndToolBar, TB_ADDBUTTONSW, 1, (LPARAM)&button);
169 }
170
171 static void AddSeparator(HWND hwndToolBar)
172 {
173     TBBUTTON button;
174
175     ZeroMemory(&button, sizeof(button));
176     button.iBitmap = -1;
177     button.idCommand = 0;
178     button.fsState = 0;
179     button.fsStyle = BTNS_SEP;
180     button.dwData = 0;
181     button.iString = -1;
182     SendMessageW(hwndToolBar, TB_ADDBUTTONSW, 1, (LPARAM)&button);
183 }
184
185 static DWORD CALLBACK stream_in(DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG *pcb)
186 {
187     HANDLE hFile = (HANDLE)cookie;
188     DWORD read;
189
190     if(!ReadFile(hFile, buffer, cb, &read, 0))
191         return 1;
192
193     *pcb = read;
194
195     return 0;
196 }
197
198 static DWORD CALLBACK stream_out(DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG *pcb)
199 {
200     DWORD written;
201     int ret;
202     HANDLE hFile = (HANDLE)cookie;
203
204     ret = WriteFile(hFile, buffer, cb, &written, 0);
205
206     if(!ret || (cb != written))
207         return 1;
208
209     *pcb = cb;
210
211     return 0;
212 }
213
214 LPWSTR file_basename(LPWSTR path)
215 {
216     LPWSTR pos = path + lstrlenW(path);
217
218     while(pos > path)
219     {
220         if(*pos == '\\' || *pos == '/')
221         {
222             pos++;
223             break;
224         }
225         pos--;
226     }
227     return pos;
228 }
229
230 static void set_caption(LPCWSTR wszNewFileName)
231 {
232     static const WCHAR wszSeparator[] = {' ','-',' '};
233     WCHAR *wszCaption;
234     SIZE_T length = 0;
235
236     if(!wszNewFileName)
237         wszNewFileName = wszDefaultFileName;
238     else
239         wszNewFileName = file_basename((LPWSTR)wszNewFileName);
240
241     wszCaption = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
242                 lstrlenW(wszNewFileName)*sizeof(WCHAR)+sizeof(wszSeparator)+sizeof(wszAppTitle));
243
244     if(!wszCaption)
245         return;
246
247     memcpy(wszCaption, wszNewFileName, lstrlenW(wszNewFileName)*sizeof(WCHAR));
248     length += lstrlenW(wszNewFileName);
249     memcpy(wszCaption + length, wszSeparator, sizeof(wszSeparator));
250     length += sizeof(wszSeparator) / sizeof(WCHAR);
251     memcpy(wszCaption + length, wszAppTitle, sizeof(wszAppTitle));
252
253     SetWindowTextW(hMainWnd, wszCaption);
254
255     HeapFree(GetProcessHeap(), 0, wszCaption);
256 }
257
258 static BOOL validate_endptr(LPCWSTR endptr, UNIT *punit)
259 {
260     if(punit != NULL)
261         *punit = UNIT_CM;
262     if(!endptr)
263         return FALSE;
264     if(!*endptr)
265         return TRUE;
266
267     while(*endptr == ' ')
268         endptr++;
269
270     if(punit == NULL)
271         return *endptr == '\0';
272
273     if(!lstrcmpW(endptr, units_cmW))
274     {
275         *punit = UNIT_CM;
276         endptr += lstrlenW(units_cmW);
277     }
278     else if (!lstrcmpW(endptr, units_inW))
279     {
280         *punit = UNIT_INCH;
281         endptr += lstrlenW(units_inW);
282     }
283     else if (!lstrcmpW(endptr, units_inchW))
284     {
285         *punit = UNIT_INCH;
286         endptr += lstrlenW(units_inchW);
287     }
288     else if (!lstrcmpW(endptr, units_ptW))
289     {
290         *punit = UNIT_PT;
291         endptr += lstrlenW(units_ptW);
292     }
293
294     return *endptr == '\0';
295 }
296
297 static BOOL number_from_string(LPCWSTR string, float *num, UNIT *punit)
298 {
299     double ret;
300     WCHAR *endptr;
301
302     *num = 0;
303     errno = 0;
304     ret = wcstod(string, &endptr);
305
306     if (punit != NULL)
307         *punit = UNIT_CM;
308     if((ret == 0 && errno != 0) || endptr == string || !validate_endptr(endptr, punit))
309     {
310         return FALSE;
311     } else
312     {
313         *num = (float)ret;
314         return TRUE;
315     }
316 }
317
318 static void set_size(float size)
319 {
320     CHARFORMAT2W fmt;
321
322     ZeroMemory(&fmt, sizeof(fmt));
323     fmt.cbSize = sizeof(fmt);
324     fmt.dwMask = CFM_SIZE;
325     fmt.yHeight = (int)(size * 20.0);
326     SendMessageW(hEditorWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt);
327 }
328
329 static void on_sizelist_modified(HWND hwndSizeList, LPWSTR wszNewFontSize)
330 {
331     WCHAR sizeBuffer[MAX_STRING_LEN];
332     CHARFORMAT2W format;
333
334     ZeroMemory(&format, sizeof(format));
335     format.cbSize = sizeof(format);
336     SendMessageW(hEditorWnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&format);
337
338     wsprintfW(sizeBuffer, stringFormat, format.yHeight / 20);
339     if(lstrcmpW(sizeBuffer, wszNewFontSize))
340     {
341         float size = 0;
342         if(number_from_string(wszNewFontSize, &size, NULL)
343            && size > 0)
344         {
345             set_size(size);
346         } else
347         {
348             SetWindowTextW(hwndSizeList, sizeBuffer);
349             MessageBoxWithResStringW(hMainWnd, MAKEINTRESOURCEW(STRING_INVALID_NUMBER),
350                         wszAppTitle, MB_OK | MB_ICONINFORMATION);
351         }
352     }
353 }
354
355 static void add_size(HWND hSizeListWnd, unsigned size)
356 {
357     WCHAR buffer[3];
358     COMBOBOXEXITEMW cbItem;
359     cbItem.mask = CBEIF_TEXT;
360     cbItem.iItem = -1;
361
362     wsprintfW(buffer, stringFormat, size);
363     cbItem.pszText = buffer;
364     SendMessageW(hSizeListWnd, CBEM_INSERTITEMW, 0, (LPARAM)&cbItem);
365 }
366
367 static void populate_size_list(HWND hSizeListWnd)
368 {
369     HWND hReBarWnd = GetDlgItem(hMainWnd, IDC_REBAR);
370     HWND hFontListWnd = GetDlgItem(hReBarWnd, IDC_FONTLIST);
371     COMBOBOXEXITEMW cbFontItem;
372     CHARFORMAT2W fmt;
373     HWND hListEditWnd = (HWND)SendMessageW(hSizeListWnd, CBEM_GETEDITCONTROL, 0, 0);
374     HDC hdc = GetDC(hMainWnd);
375     static const unsigned choices[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
376     WCHAR buffer[3];
377     size_t i;
378     DWORD fontStyle;
379
380     ZeroMemory(&fmt, sizeof(fmt));
381     fmt.cbSize = sizeof(fmt);
382     SendMessageW(hEditorWnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt);
383
384     cbFontItem.mask = CBEIF_LPARAM;
385     cbFontItem.iItem = SendMessageW(hFontListWnd, CB_FINDSTRINGEXACT, -1, (LPARAM)fmt.szFaceName);
386     SendMessageW(hFontListWnd, CBEM_GETITEMW, 0, (LPARAM)&cbFontItem);
387
388     fontStyle = (DWORD)LOWORD(cbFontItem.lParam);
389
390     SendMessageW(hSizeListWnd, CB_RESETCONTENT, 0, 0);
391
392     if((fontStyle & RASTER_FONTTYPE) && cbFontItem.iItem)
393     {
394         add_size(hSizeListWnd, (BYTE)MulDiv(HIWORD(cbFontItem.lParam), 72,
395                                GetDeviceCaps(hdc, LOGPIXELSY)));
396     } else
397     {
398         for(i = 0; i < sizeof(choices)/sizeof(choices[0]); i++)
399             add_size(hSizeListWnd, choices[i]);
400     }
401
402     wsprintfW(buffer, stringFormat, fmt.yHeight / 20);
403     SendMessageW(hListEditWnd, WM_SETTEXT, 0, (LPARAM)buffer);
404 }
405
406 static void update_size_list(void)
407 {
408     HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR);
409     HWND hwndSizeList = GetDlgItem(hReBar, IDC_SIZELIST);
410     HWND hwndSizeListEdit = (HWND)SendMessageW(hwndSizeList, CBEM_GETEDITCONTROL, 0, 0);
411     WCHAR fontSize[MAX_STRING_LEN], sizeBuffer[MAX_STRING_LEN];
412     CHARFORMAT2W fmt;
413
414     ZeroMemory(&fmt, sizeof(fmt));
415     fmt.cbSize = sizeof(fmt);
416
417     SendMessageW(hEditorWnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt);
418
419     SendMessageW(hwndSizeListEdit, WM_GETTEXT, MAX_PATH, (LPARAM)fontSize);
420     wsprintfW(sizeBuffer, stringFormat, fmt.yHeight / 20);
421
422     if(lstrcmpW(fontSize, sizeBuffer))
423         SendMessageW(hwndSizeListEdit, WM_SETTEXT, 0, (LPARAM)sizeBuffer);
424 }
425
426 static void update_font_list(void)
427 {
428     HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR);
429     HWND hFontList = GetDlgItem(hReBar, IDC_FONTLIST);
430     HWND hFontListEdit = (HWND)SendMessageW(hFontList, CBEM_GETEDITCONTROL, 0, 0);
431     WCHAR fontName[MAX_STRING_LEN];
432     CHARFORMAT2W fmt;
433
434     ZeroMemory(&fmt, sizeof(fmt));
435     fmt.cbSize = sizeof(fmt);
436
437     SendMessageW(hEditorWnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt);
438     if (!SendMessageW(hFontListEdit, WM_GETTEXT, MAX_PATH, (LPARAM)fontName)) return;
439
440     if(lstrcmpW(fontName, fmt.szFaceName))
441     {
442         SendMessageW(hFontListEdit, WM_SETTEXT, 0, (LPARAM)fmt.szFaceName);
443         populate_size_list(GetDlgItem(hReBar, IDC_SIZELIST));
444     } else
445     {
446         update_size_list();
447     }
448 }
449
450 static void clear_formatting(void)
451 {
452     PARAFORMAT2 pf;
453
454     pf.cbSize = sizeof(pf);
455     pf.dwMask = PFM_ALIGNMENT;
456     pf.wAlignment = PFA_LEFT;
457     SendMessageW(hEditorWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
458 }
459
460 static int fileformat_number(WPARAM format)
461 {
462     int number = 0;
463
464     if(format == SF_TEXT)
465     {
466         number = 1;
467     } else if (format == (SF_TEXT | SF_UNICODE))
468     {
469         number = 2;
470     }
471     return number;
472 }
473
474 static WPARAM fileformat_flags(int format)
475 {
476     WPARAM flags[] = { SF_RTF , SF_TEXT , SF_TEXT | SF_UNICODE };
477
478     return flags[format];
479 }
480
481 static void set_font(LPCWSTR wszFaceName)
482 {
483     HWND hReBarWnd = GetDlgItem(hMainWnd, IDC_REBAR);
484     HWND hSizeListWnd = GetDlgItem(hReBarWnd, IDC_SIZELIST);
485     HWND hFontListWnd = GetDlgItem(hReBarWnd, IDC_FONTLIST);
486     HWND hFontListEditWnd = (HWND)SendMessageW(hFontListWnd, CBEM_GETEDITCONTROL, 0, 0);
487     CHARFORMAT2W fmt;
488
489     ZeroMemory(&fmt, sizeof(fmt));
490
491     fmt.cbSize = sizeof(fmt);
492     fmt.dwMask = CFM_FACE;
493
494     lstrcpyW(fmt.szFaceName, wszFaceName);
495
496     SendMessageW(hEditorWnd, EM_SETCHARFORMAT,  SCF_SELECTION, (LPARAM)&fmt);
497
498     populate_size_list(hSizeListWnd);
499
500     SendMessageW(hFontListEditWnd, WM_SETTEXT, 0, (LPARAM)wszFaceName);
501 }
502
503 static void set_default_font(void)
504 {
505     static const WCHAR richTextFont[] = {'T','i','m','e','s',' ','N','e','w',' ',
506                                          'R','o','m','a','n',0};
507     static const WCHAR plainTextFont[] = {'C','o','u','r','i','e','r',' ','N','e','w',0};
508     CHARFORMAT2W fmt;
509     LPCWSTR font;
510
511     ZeroMemory(&fmt, sizeof(fmt));
512
513     fmt.cbSize = sizeof(fmt);
514     fmt.dwMask = CFM_FACE | CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE;
515     fmt.dwEffects = 0;
516
517     if(fileFormat & SF_RTF)
518         font = richTextFont;
519     else
520         font = plainTextFont;
521
522     lstrcpyW(fmt.szFaceName, font);
523
524     SendMessageW(hEditorWnd, EM_SETCHARFORMAT,  SCF_DEFAULT, (LPARAM)&fmt);
525 }
526
527 static void on_fontlist_modified(LPWSTR wszNewFaceName)
528 {
529     CHARFORMAT2W format;
530     ZeroMemory(&format, sizeof(format));
531     format.cbSize = sizeof(format);
532     SendMessageW(hEditorWnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&format);
533
534     if(lstrcmpW(format.szFaceName, wszNewFaceName))
535         set_font(wszNewFaceName);
536 }
537
538 static void add_font(LPCWSTR fontName, DWORD fontType, HWND hListWnd, const NEWTEXTMETRICEXW *ntmc)
539 {
540     COMBOBOXEXITEMW cbItem;
541     WCHAR buffer[MAX_PATH];
542     int fontHeight = 0;
543
544     cbItem.mask = CBEIF_TEXT;
545     cbItem.pszText = buffer;
546     cbItem.cchTextMax = MAX_STRING_LEN;
547     cbItem.iItem = 0;
548
549     while(SendMessageW(hListWnd, CBEM_GETITEMW, 0, (LPARAM)&cbItem))
550     {
551         if(lstrcmpiW(cbItem.pszText, fontName) <= 0)
552             cbItem.iItem++;
553         else
554             break;
555     }
556     cbItem.pszText = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(fontName) + 1)*sizeof(WCHAR) );
557     lstrcpyW( cbItem.pszText, fontName );
558
559     cbItem.mask |= CBEIF_LPARAM;
560     if(fontType & RASTER_FONTTYPE)
561         fontHeight = ntmc->ntmTm.tmHeight - ntmc->ntmTm.tmInternalLeading;
562
563     cbItem.lParam = MAKELONG(fontType,fontHeight);
564     SendMessageW(hListWnd, CBEM_INSERTITEMW, 0, (LPARAM)&cbItem);
565     HeapFree( GetProcessHeap(), 0, cbItem.pszText );
566 }
567
568 static void dialog_choose_font(void)
569 {
570     CHOOSEFONTW cf;
571     LOGFONTW lf;
572     CHARFORMAT2W fmt;
573     HDC hDC = GetDC(hMainWnd);
574
575     ZeroMemory(&cf, sizeof(cf));
576     cf.lStructSize = sizeof(cf);
577     cf.hwndOwner = hMainWnd;
578     cf.lpLogFont = &lf;
579     cf.Flags = CF_SCREENFONTS | CF_NOSCRIPTSEL | CF_INITTOLOGFONTSTRUCT | CF_EFFECTS;
580
581     ZeroMemory(&fmt, sizeof(fmt));
582     fmt.cbSize = sizeof(fmt);
583
584     SendMessageW(hEditorWnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt);
585     lstrcpyW(cf.lpLogFont->lfFaceName, fmt.szFaceName);
586     cf.lpLogFont->lfItalic = (fmt.dwEffects & CFE_ITALIC) ? TRUE : FALSE;
587     cf.lpLogFont->lfWeight = (fmt.dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL;
588     cf.lpLogFont->lfUnderline = (fmt.dwEffects & CFE_UNDERLINE) ? TRUE : FALSE;
589     cf.lpLogFont->lfStrikeOut = (fmt.dwEffects & CFE_STRIKEOUT) ? TRUE : FALSE;
590     cf.lpLogFont->lfHeight = -MulDiv(fmt.yHeight / 20, GetDeviceCaps(hDC, LOGPIXELSY), 72);
591     cf.rgbColors = fmt.crTextColor;
592
593     if(ChooseFontW(&cf))
594     {
595         ZeroMemory(&fmt, sizeof(fmt));
596         fmt.cbSize = sizeof(fmt);
597         fmt.dwMask = CFM_BOLD | CFM_ITALIC | CFM_SIZE | CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR;
598         fmt.yHeight = cf.iPointSize * 2;
599
600         if(cf.nFontType & BOLD_FONTTYPE)
601             fmt.dwEffects |= CFE_BOLD;
602         if(cf.nFontType & ITALIC_FONTTYPE)
603             fmt.dwEffects |= CFE_ITALIC;
604         if(cf.lpLogFont->lfUnderline)
605             fmt.dwEffects |= CFE_UNDERLINE;
606         if(cf.lpLogFont->lfStrikeOut)
607             fmt.dwEffects |= CFE_STRIKEOUT;
608
609         fmt.crTextColor = cf.rgbColors;
610
611         SendMessageW(hEditorWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt);
612         set_font(cf.lpLogFont->lfFaceName);
613     }
614 }
615
616
617 static int CALLBACK enum_font_proc(const LOGFONTW *lpelfe, const TEXTMETRICW *lpntme,
618                             DWORD FontType, LPARAM lParam)
619 {
620     HWND hListWnd = (HWND) lParam;
621
622     if(SendMessageW(hListWnd, CB_FINDSTRINGEXACT, -1, (LPARAM)lpelfe->lfFaceName) == CB_ERR)
623     {
624
625         add_font(lpelfe->lfFaceName, FontType, hListWnd, (const NEWTEXTMETRICEXW*)lpntme);
626     }
627
628     return 1;
629 }
630
631 static void populate_font_list(HWND hListWnd)
632 {
633     HDC hdc = GetDC(hMainWnd);
634     LOGFONTW fontinfo;
635     HWND hListEditWnd = (HWND)SendMessageW(hListWnd, CBEM_GETEDITCONTROL, 0, 0);
636     CHARFORMAT2W fmt;
637
638     fontinfo.lfCharSet = DEFAULT_CHARSET;
639     *fontinfo.lfFaceName = '\0';
640     fontinfo.lfPitchAndFamily = 0;
641
642     EnumFontFamiliesExW(hdc, &fontinfo, enum_font_proc,
643                         (LPARAM)hListWnd, 0);
644
645     ZeroMemory(&fmt, sizeof(fmt));
646     fmt.cbSize = sizeof(fmt);
647     SendMessageW(hEditorWnd, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&fmt);
648     SendMessageW(hListEditWnd, WM_SETTEXT, 0, (LPARAM)fmt.szFaceName);
649 }
650
651 static void update_window(void)
652 {
653     RECT rect;
654
655     GetClientRect(hMainWnd, &rect);
656
657     OnSize(hMainWnd, SIZE_RESTORED, MAKELPARAM(rect.right, rect.bottom));
658 }
659
660 static BOOL is_bar_visible(int bandId)
661 {
662     return barState[reg_formatindex(fileFormat)] & (1 << bandId);
663 }
664
665 static void store_bar_state(int bandId, BOOL show)
666 {
667     int formatIndex = reg_formatindex(fileFormat);
668
669     if(show)
670         barState[formatIndex] |= (1 << bandId);
671     else
672         barState[formatIndex] &= ~(1 << bandId);
673 }
674
675 static void set_toolbar_state(int bandId, BOOL show)
676 {
677     HWND hwndReBar = GetDlgItem(hMainWnd, IDC_REBAR);
678
679     SendMessageW(hwndReBar, RB_SHOWBAND, SendMessageW(hwndReBar, RB_IDTOINDEX, bandId, 0), show);
680
681     if(bandId == BANDID_TOOLBAR)
682     {
683         REBARBANDINFOW rbbinfo;
684         int index = SendMessageW(hwndReBar, RB_IDTOINDEX, BANDID_FONTLIST, 0);
685
686         rbbinfo.cbSize = REBARBANDINFOW_V6_SIZE;
687         rbbinfo.fMask = RBBIM_STYLE;
688
689         SendMessageW(hwndReBar, RB_GETBANDINFOW, index, (LPARAM)&rbbinfo);
690
691         if(!show)
692             rbbinfo.fStyle &= ~RBBS_BREAK;
693         else
694             rbbinfo.fStyle |= RBBS_BREAK;
695
696         SendMessageW(hwndReBar, RB_SETBANDINFOW, index, (LPARAM)&rbbinfo);
697     }
698
699     if(bandId == BANDID_TOOLBAR || bandId == BANDID_FORMATBAR || bandId == BANDID_RULER)
700         store_bar_state(bandId, show);
701 }
702
703 static void set_statusbar_state(BOOL show)
704 {
705     HWND hStatusWnd = GetDlgItem(hMainWnd, IDC_STATUSBAR);
706
707     ShowWindow(hStatusWnd, show ? SW_SHOW : SW_HIDE);
708     store_bar_state(BANDID_STATUSBAR, show);
709 }
710
711 static void set_bar_states(void)
712 {
713     set_toolbar_state(BANDID_TOOLBAR, is_bar_visible(BANDID_TOOLBAR));
714     set_toolbar_state(BANDID_FONTLIST, is_bar_visible(BANDID_FORMATBAR));
715     set_toolbar_state(BANDID_SIZELIST, is_bar_visible(BANDID_FORMATBAR));
716     set_toolbar_state(BANDID_FORMATBAR, is_bar_visible(BANDID_FORMATBAR));
717     set_toolbar_state(BANDID_RULER, is_bar_visible(BANDID_RULER));
718     set_statusbar_state(is_bar_visible(BANDID_STATUSBAR));
719
720     update_window();
721 }
722
723 static void preview_exit(HWND hMainWnd)
724 {
725     HMENU hMenu = LoadMenuW(GetModuleHandleW(0), MAKEINTRESOURCEW(IDM_MAINMENU));
726     HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
727
728     set_bar_states();
729     ShowWindow(hEditorWnd, TRUE);
730
731     close_preview(hMainWnd);
732
733     SetMenu(hMainWnd, hMenu);
734     registry_read_filelist(hMainWnd);
735
736     update_window();
737 }
738
739 static void set_fileformat(WPARAM format)
740 {
741     fileFormat = format;
742
743     set_bar_states();
744     set_default_font();
745     target_device(hMainWnd, wordWrap[reg_formatindex(fileFormat)]);
746 }
747
748 static void ShowOpenError(DWORD Code)
749 {
750     LPWSTR Message;
751
752     switch(Code)
753     {
754         case ERROR_ACCESS_DENIED:
755             Message = MAKEINTRESOURCEW(STRING_OPEN_ACCESS_DENIED);
756             break;
757
758         default:
759             Message = MAKEINTRESOURCEW(STRING_OPEN_FAILED);
760     }
761     MessageBoxW(hMainWnd, Message, wszAppTitle, MB_ICONEXCLAMATION | MB_OK);
762 }
763
764 static void DoOpenFile(LPCWSTR szOpenFileName)
765 {
766     HANDLE hFile;
767     EDITSTREAM es;
768     char fileStart[5];
769     DWORD readOut;
770     WPARAM format = SF_TEXT;
771
772     hFile = CreateFileW(szOpenFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
773                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
774     if (hFile == INVALID_HANDLE_VALUE)
775     {
776         ShowOpenError(GetLastError());
777         return;
778     }
779
780     ReadFile(hFile, fileStart, 5, &readOut, NULL);
781     SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
782
783     if(readOut >= 2 && (BYTE)fileStart[0] == 0xff && (BYTE)fileStart[1] == 0xfe)
784     {
785         format = SF_TEXT | SF_UNICODE;
786         SetFilePointer(hFile, 2, NULL, FILE_BEGIN);
787     } else if(readOut >= 5)
788     {
789         static const char header[] = "{\\rtf";
790         static const BYTE STG_magic[] = { 0xd0,0xcf,0x11,0xe0 };
791
792         if(!memcmp(header, fileStart, 5))
793             format = SF_RTF;
794         else if (!memcmp(STG_magic, fileStart, sizeof(STG_magic)))
795         {
796             CloseHandle(hFile);
797             MessageBoxWithResStringW(hMainWnd, MAKEINTRESOURCEW(STRING_OLE_STORAGE_NOT_SUPPORTED),
798                     wszAppTitle, MB_OK | MB_ICONEXCLAMATION);
799             return;
800         }
801     }
802
803     es.dwCookie = (DWORD_PTR)hFile;
804     es.pfnCallback = stream_in;
805
806     clear_formatting();
807     set_fileformat(format);
808     SendMessageW(hEditorWnd, EM_STREAMIN, format, (LPARAM)&es);
809
810     CloseHandle(hFile);
811
812     SetFocus(hEditorWnd);
813
814     set_caption(szOpenFileName);
815
816     lstrcpyW(wszFileName, szOpenFileName);
817     SendMessageW(hEditorWnd, EM_SETMODIFY, FALSE, 0);
818     registry_set_filelist(szOpenFileName, hMainWnd);
819     update_font_list();
820 }
821
822 static void ShowWriteError(DWORD Code)
823 {
824     LPWSTR Message;
825
826     switch(Code)
827     {
828         case ERROR_ACCESS_DENIED:
829             Message = MAKEINTRESOURCEW(STRING_WRITE_ACCESS_DENIED);
830             break;
831
832         default:
833             Message = MAKEINTRESOURCEW(STRING_WRITE_FAILED);
834     }
835     MessageBoxW(hMainWnd, Message, wszAppTitle, MB_ICONEXCLAMATION | MB_OK);
836 }
837
838 static BOOL DoSaveFile(LPCWSTR wszSaveFileName, WPARAM format)
839 {
840     HANDLE hFile;
841     EDITSTREAM stream;
842     LRESULT ret;
843
844     hFile = CreateFileW(wszSaveFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
845         FILE_ATTRIBUTE_NORMAL, NULL);
846
847     if(hFile == INVALID_HANDLE_VALUE)
848     {
849         ShowWriteError(GetLastError());
850         return FALSE;
851     }
852
853     if(format == (SF_TEXT | SF_UNICODE))
854     {
855         static const BYTE unicode[] = {0xff,0xfe};
856         DWORD writeOut;
857         WriteFile(hFile, &unicode, sizeof(unicode), &writeOut, 0);
858
859         if(writeOut != sizeof(unicode))
860         {
861             CloseHandle(hFile);
862             return FALSE;
863         }
864     }
865
866     stream.dwCookie = (DWORD_PTR)hFile;
867     stream.pfnCallback = stream_out;
868
869     ret = SendMessageW(hEditorWnd, EM_STREAMOUT, format, (LPARAM)&stream);
870
871     CloseHandle(hFile);
872
873     SetFocus(hEditorWnd);
874
875     if(!ret)
876     {
877         GETTEXTLENGTHEX gt;
878         gt.flags = GTL_DEFAULT;
879         gt.codepage = 1200;
880
881         if(SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, 0))
882             return FALSE;
883     }
884
885     lstrcpyW(wszFileName, wszSaveFileName);
886     set_caption(wszFileName);
887     SendMessageW(hEditorWnd, EM_SETMODIFY, FALSE, 0);
888     set_fileformat(format);
889
890     return TRUE;
891 }
892
893 static BOOL DialogSaveFile(void)
894 {
895     OPENFILENAMEW sfn;
896
897     WCHAR wszFile[MAX_PATH] = {'\0'};
898     static const WCHAR wszDefExt[] = {'r','t','f','\0'};
899
900     ZeroMemory(&sfn, sizeof(sfn));
901
902     sfn.lStructSize = sizeof(sfn);
903     sfn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_ENABLESIZING;
904     sfn.hwndOwner = hMainWnd;
905     sfn.lpstrFilter = wszFilter;
906     sfn.lpstrFile = wszFile;
907     sfn.nMaxFile = MAX_PATH;
908     sfn.lpstrDefExt = wszDefExt;
909     sfn.nFilterIndex = fileformat_number(fileFormat)+1;
910
911     while(GetSaveFileNameW(&sfn))
912     {
913         if(fileformat_flags(sfn.nFilterIndex-1) != SF_RTF)
914         {
915             if(MessageBoxWithResStringW(hMainWnd, MAKEINTRESOURCEW(STRING_SAVE_LOSEFORMATTING),
916                            wszAppTitle, MB_YESNO | MB_ICONEXCLAMATION) != IDYES)
917                 continue;
918         }
919         return DoSaveFile(sfn.lpstrFile, fileformat_flags(sfn.nFilterIndex-1));
920     }
921     return FALSE;
922 }
923
924 static BOOL prompt_save_changes(void)
925 {
926     if(!wszFileName[0])
927     {
928         GETTEXTLENGTHEX gt;
929         gt.flags = GTL_NUMCHARS;
930         gt.codepage = 1200;
931         if(!SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, 0))
932             return TRUE;
933     }
934
935     if(!SendMessageW(hEditorWnd, EM_GETMODIFY, 0, 0))
936     {
937         return TRUE;
938     } else
939     {
940         LPWSTR displayFileName;
941         WCHAR *text;
942         int ret;
943
944         if(!wszFileName[0])
945             displayFileName = wszDefaultFileName;
946         else
947             displayFileName = file_basename(wszFileName);
948
949         text = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
950                          (lstrlenW(displayFileName)+lstrlenW(wszSaveChanges))*sizeof(WCHAR));
951
952         if(!text)
953             return FALSE;
954
955         wsprintfW(text, wszSaveChanges, displayFileName);
956
957         ret = MessageBoxW(hMainWnd, text, wszAppTitle, MB_YESNOCANCEL | MB_ICONEXCLAMATION);
958
959         HeapFree(GetProcessHeap(), 0, text);
960
961         switch(ret)
962         {
963             case IDNO:
964                 return TRUE;
965
966             case IDYES:
967                 if(wszFileName[0])
968                     return DoSaveFile(wszFileName, fileFormat);
969                 return DialogSaveFile();
970
971             default:
972                 return FALSE;
973         }
974     }
975 }
976
977 static void DialogOpenFile(void)
978 {
979     OPENFILENAMEW ofn;
980
981     WCHAR wszFile[MAX_PATH] = {'\0'};
982     static const WCHAR wszDefExt[] = {'r','t','f','\0'};
983
984     ZeroMemory(&ofn, sizeof(ofn));
985
986     ofn.lStructSize = sizeof(ofn);
987     ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_ENABLESIZING;
988     ofn.hwndOwner = hMainWnd;
989     ofn.lpstrFilter = wszFilter;
990     ofn.lpstrFile = wszFile;
991     ofn.nMaxFile = MAX_PATH;
992     ofn.lpstrDefExt = wszDefExt;
993     ofn.nFilterIndex = fileformat_number(fileFormat)+1;
994
995     if(GetOpenFileNameW(&ofn))
996     {
997         if(prompt_save_changes())
998             DoOpenFile(ofn.lpstrFile);
999     }
1000 }
1001
1002 static void dialog_about(void)
1003 {
1004     HICON icon = LoadImageW(GetModuleHandleW(0), MAKEINTRESOURCEW(IDI_WORDPAD), IMAGE_ICON, 48, 48, LR_SHARED);
1005     ShellAboutW(hMainWnd, wszAppTitle, 0, icon);
1006 }
1007
1008 static INT_PTR CALLBACK formatopts_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1009 {
1010     switch(message)
1011     {
1012         case WM_INITDIALOG:
1013             {
1014                 LPPROPSHEETPAGEW ps = (LPPROPSHEETPAGEW)lParam;
1015                 int wrap = -1;
1016                 char id[4];
1017                 HWND hIdWnd = GetDlgItem(hWnd, IDC_PAGEFMT_ID);
1018
1019                 sprintf(id, "%d\n", (int)ps->lParam);
1020                 SetWindowTextA(hIdWnd, id);
1021                 if(wordWrap[ps->lParam] == ID_WORDWRAP_NONE)
1022                     wrap = IDC_PAGEFMT_WN;
1023                 else if(wordWrap[ps->lParam] == ID_WORDWRAP_WINDOW)
1024                     wrap = IDC_PAGEFMT_WW;
1025                 else if(wordWrap[ps->lParam] == ID_WORDWRAP_MARGIN)
1026                     wrap = IDC_PAGEFMT_WM;
1027
1028                 if(wrap != -1)
1029                     CheckRadioButton(hWnd, IDC_PAGEFMT_WN,
1030                                      IDC_PAGEFMT_WM, wrap);
1031
1032                 if(barState[ps->lParam] & (1 << BANDID_TOOLBAR))
1033                     CheckDlgButton(hWnd, IDC_PAGEFMT_TB, TRUE);
1034                 if(barState[ps->lParam] & (1 << BANDID_FORMATBAR))
1035                     CheckDlgButton(hWnd, IDC_PAGEFMT_FB, TRUE);
1036                 if(barState[ps->lParam] & (1 << BANDID_RULER))
1037                     CheckDlgButton(hWnd, IDC_PAGEFMT_RU, TRUE);
1038                 if(barState[ps->lParam] & (1 << BANDID_STATUSBAR))
1039                     CheckDlgButton(hWnd, IDC_PAGEFMT_SB, TRUE);
1040             }
1041             break;
1042
1043         case WM_COMMAND:
1044             switch(LOWORD(wParam))
1045             {
1046                 case IDC_PAGEFMT_WN:
1047                 case IDC_PAGEFMT_WW:
1048                 case IDC_PAGEFMT_WM:
1049                     CheckRadioButton(hWnd, IDC_PAGEFMT_WN, IDC_PAGEFMT_WM,
1050                                      LOWORD(wParam));
1051                     break;
1052
1053                 case IDC_PAGEFMT_TB:
1054                 case IDC_PAGEFMT_FB:
1055                 case IDC_PAGEFMT_RU:
1056                 case IDC_PAGEFMT_SB:
1057                     CheckDlgButton(hWnd, LOWORD(wParam),
1058                                    !IsDlgButtonChecked(hWnd, LOWORD(wParam)));
1059                     break;
1060             }
1061             break;
1062         case WM_NOTIFY:
1063             {
1064                 LPNMHDR header = (LPNMHDR)lParam;
1065                 if(header->code == PSN_APPLY)
1066                 {
1067                     HWND hIdWnd = GetDlgItem(hWnd, IDC_PAGEFMT_ID);
1068                     char sid[4];
1069                     int id;
1070
1071                     GetWindowTextA(hIdWnd, sid, 4);
1072                     id = atoi(sid);
1073                     if(IsDlgButtonChecked(hWnd, IDC_PAGEFMT_WN))
1074                         wordWrap[id] = ID_WORDWRAP_NONE;
1075                     else if(IsDlgButtonChecked(hWnd, IDC_PAGEFMT_WW))
1076                         wordWrap[id] = ID_WORDWRAP_WINDOW;
1077                     else if(IsDlgButtonChecked(hWnd, IDC_PAGEFMT_WM))
1078                         wordWrap[id] = ID_WORDWRAP_MARGIN;
1079
1080                     if(IsDlgButtonChecked(hWnd, IDC_PAGEFMT_TB))
1081                         barState[id] |= (1 << BANDID_TOOLBAR);
1082                     else
1083                         barState[id] &= ~(1 << BANDID_TOOLBAR);
1084
1085                     if(IsDlgButtonChecked(hWnd, IDC_PAGEFMT_FB))
1086                         barState[id] |= (1 << BANDID_FORMATBAR);
1087                     else
1088                         barState[id] &= ~(1 << BANDID_FORMATBAR);
1089
1090                     if(IsDlgButtonChecked(hWnd, IDC_PAGEFMT_RU))
1091                         barState[id] |= (1 << BANDID_RULER);
1092                     else
1093                         barState[id] &= ~(1 << BANDID_RULER);
1094
1095                     if(IsDlgButtonChecked(hWnd, IDC_PAGEFMT_SB))
1096                         barState[id] |= (1 << BANDID_STATUSBAR);
1097                     else
1098                         barState[id] &= ~(1 << BANDID_STATUSBAR);
1099                 }
1100             }
1101             break;
1102     }
1103     return FALSE;
1104 }
1105
1106 static void dialog_viewproperties(void)
1107 {
1108     PROPSHEETPAGEW psp[2];
1109     PROPSHEETHEADERW psh;
1110     size_t i;
1111     HINSTANCE hInstance = GetModuleHandleW(0);
1112     LPCPROPSHEETPAGEW ppsp = (LPCPROPSHEETPAGEW)&psp;
1113
1114     psp[0].dwSize = sizeof(PROPSHEETPAGEW);
1115     psp[0].dwFlags = PSP_USETITLE;
1116     U(psp[0]).pszTemplate = MAKEINTRESOURCEW(IDD_FORMATOPTS);
1117     psp[0].pfnDlgProc = formatopts_proc;
1118     psp[0].hInstance = hInstance;
1119     psp[0].lParam = reg_formatindex(SF_TEXT);
1120     psp[0].pfnCallback = NULL;
1121     psp[0].pszTitle = MAKEINTRESOURCEW(STRING_VIEWPROPS_TEXT);
1122     for(i = 1; i < sizeof(psp)/sizeof(psp[0]); i++)
1123     {
1124         psp[i].dwSize = psp[0].dwSize;
1125         psp[i].dwFlags = psp[0].dwFlags;
1126         U(psp[i]).pszTemplate = U(psp[0]).pszTemplate;
1127         psp[i].pfnDlgProc = psp[0].pfnDlgProc;
1128         psp[i].hInstance = psp[0].hInstance;
1129         psp[i].lParam = reg_formatindex(SF_RTF);
1130         psp[i].pfnCallback = psp[0].pfnCallback;
1131         psp[i].pszTitle = MAKEINTRESOURCEW(STRING_VIEWPROPS_RICHTEXT);
1132     }
1133
1134     psh.dwSize = sizeof(psh);
1135     psh.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW;
1136     psh.hwndParent = hMainWnd;
1137     psh.hInstance = hInstance;
1138     psh.pszCaption = MAKEINTRESOURCEW(STRING_VIEWPROPS_TITLE);
1139     psh.nPages = sizeof(psp)/sizeof(psp[0]);
1140     U3(psh).ppsp = ppsp;
1141     U(psh).pszIcon = MAKEINTRESOURCEW(IDI_WORDPAD);
1142
1143     if(fileFormat & SF_RTF)
1144         U2(psh).nStartPage = 1;
1145     else
1146         U2(psh).nStartPage = 0;
1147     PropertySheetW(&psh);
1148     set_bar_states();
1149     target_device(hMainWnd, wordWrap[reg_formatindex(fileFormat)]);
1150 }
1151
1152 static void HandleCommandLine(LPWSTR cmdline)
1153 {
1154     WCHAR delimiter;
1155     int opt_print = 0;
1156
1157     /* skip white space */
1158     while (*cmdline == ' ') cmdline++;
1159
1160     /* skip executable name */
1161     delimiter = (*cmdline == '"' ? '"' : ' ');
1162
1163     if (*cmdline == delimiter) cmdline++;
1164     while (*cmdline && *cmdline != delimiter) cmdline++;
1165     if (*cmdline == delimiter) cmdline++;
1166
1167     while (*cmdline)
1168     {
1169         while (isspace(*cmdline)) cmdline++;
1170
1171         if (*cmdline == '-' || *cmdline == '/')
1172         {
1173             if (!cmdline[2] || isspace(cmdline[2]))
1174             {
1175                 switch (cmdline[1])
1176                 {
1177                 case 'P':
1178                 case 'p':
1179                     opt_print = 1;
1180                     cmdline += 2;
1181                     continue;
1182                 }
1183             }
1184             /* a filename starting by / */
1185         }
1186         break;
1187     }
1188
1189     if (*cmdline)
1190     {
1191         /* file name is passed on the command line */
1192         if (cmdline[0] == '"')
1193         {
1194             cmdline++;
1195             cmdline[lstrlenW(cmdline) - 1] = 0;
1196         }
1197         DoOpenFile(cmdline);
1198         InvalidateRect(hMainWnd, NULL, FALSE);
1199     }
1200
1201     if (opt_print)
1202         MessageBoxWithResStringW(hMainWnd, MAKEINTRESOURCEW(STRING_PRINTING_NOT_IMPLEMENTED), wszAppTitle, MB_OK);
1203 }
1204
1205 static LRESULT handle_findmsg(LPFINDREPLACEW pFr)
1206 {
1207     if(pFr->Flags & FR_DIALOGTERM)
1208     {
1209         hFindWnd = 0;
1210         pFr->Flags = FR_FINDNEXT;
1211         return 0;
1212     }
1213
1214     if(pFr->Flags & FR_FINDNEXT || pFr->Flags & FR_REPLACE || pFr->Flags & FR_REPLACEALL)
1215     {
1216         FINDREPLACE_custom *custom_data = (FINDREPLACE_custom*)pFr->lCustData;
1217         DWORD flags;
1218         FINDTEXTEXW ft;
1219         CHARRANGE sel;
1220         LRESULT ret = -1;
1221         HMENU hMenu = GetMenu(hMainWnd);
1222         MENUITEMINFOW mi;
1223
1224         mi.cbSize = sizeof(mi);
1225         mi.fMask = MIIM_DATA;
1226         mi.dwItemData = 1;
1227         SetMenuItemInfoW(hMenu, ID_FIND_NEXT, FALSE, &mi);
1228
1229         /* Make sure find field is saved. */
1230         if (pFr->lpstrFindWhat != custom_data->findBuffer)
1231         {
1232             lstrcpynW(custom_data->findBuffer, pFr->lpstrFindWhat,
1233                       sizeof(custom_data->findBuffer));
1234             pFr->lpstrFindWhat = custom_data->findBuffer;
1235         }
1236
1237         SendMessageW(hEditorWnd, EM_GETSEL, (WPARAM)&sel.cpMin, (LPARAM)&sel.cpMax);
1238         if(custom_data->endPos == -1) {
1239             custom_data->endPos = sel.cpMin;
1240             custom_data->wrapped = FALSE;
1241         }
1242
1243         flags = FR_DOWN | (pFr->Flags & (FR_MATCHCASE | FR_WHOLEWORD));
1244         ft.lpstrText = pFr->lpstrFindWhat;
1245
1246         /* Only replace the existing selection if it is an exact match. */
1247         if (sel.cpMin != sel.cpMax &&
1248             (pFr->Flags & FR_REPLACE || pFr->Flags & FR_REPLACEALL))
1249         {
1250             ft.chrg = sel;
1251             SendMessageW(hEditorWnd, EM_FINDTEXTEXW, flags, (LPARAM)&ft);
1252             if (ft.chrgText.cpMin == sel.cpMin && ft.chrgText.cpMax == sel.cpMax) {
1253                 SendMessageW(hEditorWnd, EM_REPLACESEL, TRUE, (LPARAM)pFr->lpstrReplaceWith);
1254                 SendMessageW(hEditorWnd, EM_GETSEL, (WPARAM)&sel.cpMin, (LPARAM)&sel.cpMax);
1255             }
1256         }
1257
1258         /* Search from the start of the selection, but exclude the first character
1259          * from search if there is a selection. */
1260         ft.chrg.cpMin = sel.cpMin;
1261         if (sel.cpMin != sel.cpMax)
1262             ft.chrg.cpMin++;
1263
1264         /* Search to the end, then wrap around and search from the start. */
1265         if (!custom_data->wrapped) {
1266             ft.chrg.cpMax = -1;
1267             ret = SendMessageW(hEditorWnd, EM_FINDTEXTEXW, flags, (LPARAM)&ft);
1268             if (ret == -1) {
1269                 custom_data->wrapped = TRUE;
1270                 ft.chrg.cpMin = 0;
1271             }
1272         }
1273
1274         if (ret == -1) {
1275             ft.chrg.cpMax = custom_data->endPos + lstrlenW(pFr->lpstrFindWhat) - 1;
1276             if (ft.chrg.cpMax > ft.chrg.cpMin)
1277                 ret = SendMessageW(hEditorWnd, EM_FINDTEXTEXW, flags, (LPARAM)&ft);
1278         }
1279
1280         if (ret == -1) {
1281             custom_data->endPos = -1;
1282             EnableWindow(hMainWnd, FALSE);
1283             MessageBoxWithResStringW(hFindWnd, MAKEINTRESOURCEW(STRING_SEARCH_FINISHED),
1284                                      wszAppTitle, MB_OK | MB_ICONASTERISK | MB_TASKMODAL);
1285             EnableWindow(hMainWnd, TRUE);
1286         } else {
1287             SendMessageW(hEditorWnd, EM_SETSEL, ft.chrgText.cpMin, ft.chrgText.cpMax);
1288             SendMessageW(hEditorWnd, EM_SCROLLCARET, 0, 0);
1289
1290             if (pFr->Flags & FR_REPLACEALL)
1291                 return handle_findmsg(pFr);
1292         }
1293     }
1294
1295     return 0;
1296 }
1297
1298 static void dialog_find(LPFINDREPLACEW fr, BOOL replace)
1299 {
1300     static WCHAR selBuffer[128];
1301     static WCHAR replaceBuffer[128];
1302     static FINDREPLACE_custom custom_data;
1303     static const WCHAR endl = '\r';
1304     FINDTEXTW ft;
1305
1306     /* Allow only one search/replace dialog to open */
1307     if(hFindWnd != NULL)
1308     {
1309         SetActiveWindow(hFindWnd);
1310         return;
1311     }
1312
1313     ZeroMemory(fr, sizeof(FINDREPLACEW));
1314     fr->lStructSize = sizeof(FINDREPLACEW);
1315     fr->hwndOwner = hMainWnd;
1316     fr->Flags = FR_HIDEUPDOWN;
1317     /* Find field is filled with the selected text if it is non-empty
1318      * and stays within the same paragraph, otherwise the previous
1319      * find field is used. */
1320     SendMessageW(hEditorWnd, EM_GETSEL, (WPARAM)&ft.chrg.cpMin,
1321                  (LPARAM)&ft.chrg.cpMax);
1322     ft.lpstrText = &endl;
1323     if (ft.chrg.cpMin != ft.chrg.cpMax &&
1324         SendMessageW(hEditorWnd, EM_FINDTEXTW, FR_DOWN, (LPARAM)&ft) == -1)
1325     {
1326         /* Use a temporary buffer for the selected text so that the saved
1327          * find field is only overwritten when a find/replace is clicked. */
1328         GETTEXTEX gt = {sizeof(selBuffer), GT_SELECTION, 1200, NULL, NULL};
1329         SendMessageW(hEditorWnd, EM_GETTEXTEX, (WPARAM)&gt, (LPARAM)selBuffer);
1330         fr->lpstrFindWhat = selBuffer;
1331     } else {
1332         fr->lpstrFindWhat = custom_data.findBuffer;
1333     }
1334     fr->lpstrReplaceWith = replaceBuffer;
1335     custom_data.endPos = -1;
1336     custom_data.wrapped = FALSE;
1337     fr->lCustData = (LPARAM)&custom_data;
1338     fr->wFindWhatLen = sizeof(custom_data.findBuffer);
1339     fr->wReplaceWithLen = sizeof(replaceBuffer);
1340
1341     if(replace)
1342         hFindWnd = ReplaceTextW(fr);
1343     else
1344         hFindWnd = FindTextW(fr);
1345 }
1346
1347 static int units_to_twips(UNIT unit, float number)
1348 {
1349     int twips = 0;
1350
1351     switch(unit)
1352     {
1353     case UNIT_CM:
1354         twips = (int)(number * 1000.0 / (float)CENTMM_PER_INCH * (float)TWIPS_PER_INCH);
1355         break;
1356
1357     case UNIT_INCH:
1358         twips = (int)(number * (float)TWIPS_PER_INCH);
1359         break;
1360
1361     case UNIT_PT:
1362         twips = (int)(number * (0.0138 * (float)TWIPS_PER_INCH));
1363         break;
1364     }
1365
1366     return twips;
1367 }
1368
1369 static void append_current_units(LPWSTR buffer)
1370 {
1371     static const WCHAR space[] = {' ', 0};
1372     lstrcatW(buffer, space);
1373     lstrcatW(buffer, units_cmW);
1374 }
1375
1376 static void number_with_units(LPWSTR buffer, int number)
1377 {
1378     static const WCHAR fmt[] = {'%','.','2','f',' ','%','s','\0'};
1379     float converted = (float)number / (float)TWIPS_PER_INCH *(float)CENTMM_PER_INCH / 1000.0;
1380
1381     sprintfW(buffer, fmt, converted, units_cmW);
1382 }
1383
1384 static BOOL get_comboexlist_selection(HWND hComboEx, LPWSTR wszBuffer, UINT bufferLength)
1385 {
1386     COMBOBOXEXITEMW cbItem;
1387     COMBOBOXINFO cbInfo;
1388     HWND hCombo, hList;
1389     int idx, result;
1390
1391     hCombo = (HWND)SendMessageW(hComboEx, CBEM_GETCOMBOCONTROL, 0, 0);
1392     if (!hCombo)
1393         return FALSE;
1394     cbInfo.cbSize = sizeof(COMBOBOXINFO);
1395     result = SendMessageW(hCombo, CB_GETCOMBOBOXINFO, 0, (LPARAM)&cbInfo);
1396     if (!result)
1397         return FALSE;
1398     hList = cbInfo.hwndList;
1399     idx = SendMessageW(hList, LB_GETCURSEL, 0, 0);
1400     if (idx < 0)
1401         return FALSE;
1402
1403     ZeroMemory(&cbItem, sizeof(cbItem));
1404     cbItem.mask = CBEIF_TEXT;
1405     cbItem.iItem = idx;
1406     cbItem.pszText = wszBuffer;
1407     cbItem.cchTextMax = bufferLength-1;
1408     result = SendMessageW(hComboEx, CBEM_GETITEMW, 0, (LPARAM)&cbItem);
1409
1410     return result != 0;
1411 }
1412
1413 static INT_PTR CALLBACK datetime_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1414 {
1415     switch(message)
1416     {
1417         case WM_INITDIALOG:
1418             {
1419                 WCHAR buffer[MAX_STRING_LEN];
1420                 SYSTEMTIME st;
1421                 HWND hListWnd = GetDlgItem(hWnd, IDC_DATETIME);
1422                 GetLocalTime(&st);
1423
1424                 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, 0, (LPWSTR)&buffer,
1425                                MAX_STRING_LEN);
1426                 SendMessageW(hListWnd, LB_ADDSTRING, 0, (LPARAM)&buffer);
1427                 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, 0, (LPWSTR)&buffer,
1428                                MAX_STRING_LEN);
1429                 SendMessageW(hListWnd, LB_ADDSTRING, 0, (LPARAM)&buffer);
1430                 GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, 0, (LPWSTR)&buffer, MAX_STRING_LEN);
1431                 SendMessageW(hListWnd, LB_ADDSTRING, 0, (LPARAM)&buffer);
1432
1433                 SendMessageW(hListWnd, LB_SETSEL, TRUE, 0);
1434             }
1435             break;
1436
1437         case WM_COMMAND:
1438             switch(LOWORD(wParam))
1439             {
1440                 case IDC_DATETIME:
1441                     if (HIWORD(wParam) != LBN_DBLCLK)
1442                         break;
1443                     /* Fall through */
1444
1445                 case IDOK:
1446                     {
1447                         LRESULT index;
1448                         HWND hListWnd = GetDlgItem(hWnd, IDC_DATETIME);
1449
1450                         index = SendMessageW(hListWnd, LB_GETCURSEL, 0, 0);
1451
1452                         if(index != LB_ERR)
1453                         {
1454                             WCHAR buffer[MAX_STRING_LEN];
1455                             SendMessageW(hListWnd, LB_GETTEXT, index, (LPARAM)&buffer);
1456                             SendMessageW(hEditorWnd, EM_REPLACESEL, TRUE, (LPARAM)&buffer);
1457                         }
1458                     }
1459                     /* Fall through */
1460
1461                 case IDCANCEL:
1462                     EndDialog(hWnd, wParam);
1463                     return TRUE;
1464             }
1465     }
1466     return FALSE;
1467 }
1468
1469 static INT_PTR CALLBACK newfile_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1470 {
1471     switch(message)
1472     {
1473         case WM_INITDIALOG:
1474             {
1475                 HINSTANCE hInstance = GetModuleHandleW(0);
1476                 WCHAR buffer[MAX_STRING_LEN];
1477                 HWND hListWnd = GetDlgItem(hWnd, IDC_NEWFILE);
1478
1479                 LoadStringW(hInstance, STRING_NEWFILE_RICHTEXT, buffer, MAX_STRING_LEN);
1480                 SendMessageW(hListWnd, LB_ADDSTRING, 0, (LPARAM)&buffer);
1481                 LoadStringW(hInstance, STRING_NEWFILE_TXT, buffer, MAX_STRING_LEN);
1482                 SendMessageW(hListWnd, LB_ADDSTRING, 0, (LPARAM)&buffer);
1483                 LoadStringW(hInstance, STRING_NEWFILE_TXT_UNICODE, buffer, MAX_STRING_LEN);
1484                 SendMessageW(hListWnd, LB_ADDSTRING, 0, (LPARAM)&buffer);
1485
1486                 SendMessageW(hListWnd, LB_SETSEL, TRUE, 0);
1487             }
1488             break;
1489
1490         case WM_COMMAND:
1491             switch(LOWORD(wParam))
1492             {
1493                 case IDOK:
1494                     {
1495                         LRESULT index;
1496                         HWND hListWnd = GetDlgItem(hWnd, IDC_NEWFILE);
1497                         index = SendMessageW(hListWnd, LB_GETCURSEL, 0, 0);
1498
1499                         if(index != LB_ERR)
1500                             EndDialog(hWnd, MAKELONG(fileformat_flags(index),0));
1501                     }
1502                     return TRUE;
1503
1504                 case IDCANCEL:
1505                     EndDialog(hWnd, MAKELONG(ID_NEWFILE_ABORT,0));
1506                     return TRUE;
1507             }
1508     }
1509     return FALSE;
1510 }
1511
1512 static INT_PTR CALLBACK paraformat_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1513 {
1514     static const WORD ALIGNMENT_VALUES[] = {PFA_LEFT, PFA_RIGHT, PFA_CENTER};
1515
1516     switch(message)
1517     {
1518         case WM_INITDIALOG:
1519             {
1520                 HINSTANCE hInstance = GetModuleHandleW(0);
1521                 WCHAR buffer[MAX_STRING_LEN];
1522                 HWND hListWnd = GetDlgItem(hWnd, IDC_PARA_ALIGN);
1523                 HWND hLeftWnd = GetDlgItem(hWnd, IDC_PARA_LEFT);
1524                 HWND hRightWnd = GetDlgItem(hWnd, IDC_PARA_RIGHT);
1525                 HWND hFirstWnd = GetDlgItem(hWnd, IDC_PARA_FIRST);
1526                 PARAFORMAT2 pf;
1527                 int index = 0;
1528
1529                 LoadStringW(hInstance, STRING_ALIGN_LEFT, buffer,
1530                             MAX_STRING_LEN);
1531                 SendMessageW(hListWnd, CB_ADDSTRING, 0, (LPARAM)buffer);
1532                 LoadStringW(hInstance, STRING_ALIGN_RIGHT, buffer,
1533                             MAX_STRING_LEN);
1534                 SendMessageW(hListWnd, CB_ADDSTRING, 0, (LPARAM)buffer);
1535                 LoadStringW(hInstance, STRING_ALIGN_CENTER, buffer,
1536                             MAX_STRING_LEN);
1537                 SendMessageW(hListWnd, CB_ADDSTRING, 0, (LPARAM)buffer);
1538
1539                 pf.cbSize = sizeof(pf);
1540                 pf.dwMask = PFM_ALIGNMENT | PFM_OFFSET | PFM_RIGHTINDENT |
1541                             PFM_STARTINDENT;
1542                 SendMessageW(hEditorWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
1543
1544                 if(pf.wAlignment == PFA_RIGHT)
1545                     index ++;
1546                 else if(pf.wAlignment == PFA_CENTER)
1547                     index += 2;
1548
1549                 SendMessageW(hListWnd, CB_SETCURSEL, index, 0);
1550
1551                 number_with_units(buffer, pf.dxStartIndent + pf.dxOffset);
1552                 SetWindowTextW(hLeftWnd, buffer);
1553                 number_with_units(buffer, pf.dxRightIndent);
1554                 SetWindowTextW(hRightWnd, buffer);
1555                 number_with_units(buffer, -pf.dxOffset);
1556                 SetWindowTextW(hFirstWnd, buffer);
1557             }
1558             break;
1559
1560         case WM_COMMAND:
1561             switch(LOWORD(wParam))
1562             {
1563                 case IDOK:
1564                     {
1565                         HWND hListWnd = GetDlgItem(hWnd, IDC_PARA_ALIGN);
1566                         HWND hLeftWnd = GetDlgItem(hWnd, IDC_PARA_LEFT);
1567                         HWND hRightWnd = GetDlgItem(hWnd, IDC_PARA_RIGHT);
1568                         HWND hFirstWnd = GetDlgItem(hWnd, IDC_PARA_FIRST);
1569                         WCHAR buffer[MAX_STRING_LEN];
1570                         int index;
1571                         float num;
1572                         int ret = 0;
1573                         PARAFORMAT pf;
1574                         UNIT unit;
1575
1576                         index = SendMessageW(hListWnd, CB_GETCURSEL, 0, 0);
1577                         pf.wAlignment = ALIGNMENT_VALUES[index];
1578
1579                         GetWindowTextW(hLeftWnd, buffer, MAX_STRING_LEN);
1580                         if(number_from_string(buffer, &num, &unit))
1581                             ret++;
1582                         pf.dxOffset = units_to_twips(unit, num);
1583                         GetWindowTextW(hRightWnd, buffer, MAX_STRING_LEN);
1584                         if(number_from_string(buffer, &num, &unit))
1585                             ret++;
1586                         pf.dxRightIndent = units_to_twips(unit, num);
1587                         GetWindowTextW(hFirstWnd, buffer, MAX_STRING_LEN);
1588                         if(number_from_string(buffer, &num, &unit))
1589                             ret++;
1590                         pf.dxStartIndent = units_to_twips(unit, num);
1591
1592                         if(ret != 3)
1593                         {
1594                             MessageBoxWithResStringW(hMainWnd, MAKEINTRESOURCEW(STRING_INVALID_NUMBER),
1595                                         wszAppTitle, MB_OK | MB_ICONASTERISK);
1596                             return FALSE;
1597                         } else
1598                         {
1599                             if (pf.dxOffset + pf.dxStartIndent < 0
1600                                 && pf.dxStartIndent < 0)
1601                             {
1602                                 /* The first line is before the left edge, so
1603                                  * make sure it is at the left edge. */
1604                                 pf.dxOffset = -pf.dxStartIndent;
1605                             } else if (pf.dxOffset < 0) {
1606                                 /* The second and following lines are before
1607                                  * the left edge, so set it to be at the left
1608                                  * edge, and adjust the first line since it
1609                                  * is relative to it. */
1610                                 pf.dxStartIndent = max(pf.dxStartIndent + pf.dxOffset, 0);
1611                                 pf.dxOffset = 0;
1612                             }
1613                             /* Internally the dxStartIndent is the absolute
1614                              * offset for the first line and dxOffset is
1615                              * to it value as opposed how it is displayed with
1616                              * the first line being the relative value.
1617                              * These two lines make the adjustments. */
1618                             pf.dxStartIndent = pf.dxStartIndent + pf.dxOffset;
1619                             pf.dxOffset = pf.dxOffset - pf.dxStartIndent;
1620
1621                             pf.cbSize = sizeof(pf);
1622                             pf.dwMask = PFM_ALIGNMENT | PFM_OFFSET | PFM_RIGHTINDENT |
1623                                         PFM_STARTINDENT;
1624                             SendMessageW(hEditorWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
1625                         }
1626                     }
1627                     /* Fall through */
1628
1629                 case IDCANCEL:
1630                     EndDialog(hWnd, wParam);
1631                     return TRUE;
1632             }
1633     }
1634     return FALSE;
1635 }
1636
1637 static INT_PTR CALLBACK tabstops_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1638 {
1639     switch(message)
1640     {
1641         case WM_INITDIALOG:
1642             {
1643                 HWND hTabWnd = GetDlgItem(hWnd, IDC_TABSTOPS);
1644                 PARAFORMAT pf;
1645                 WCHAR buffer[MAX_STRING_LEN];
1646                 int i;
1647
1648                 pf.cbSize = sizeof(pf);
1649                 pf.dwMask = PFM_TABSTOPS;
1650                 SendMessageW(hEditorWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
1651                 SendMessageW(hTabWnd, CB_LIMITTEXT, MAX_STRING_LEN-1, 0);
1652
1653                 for(i = 0; i < pf.cTabCount; i++)
1654                 {
1655                     number_with_units(buffer, pf.rgxTabs[i]);
1656                     SendMessageW(hTabWnd, CB_ADDSTRING, 0, (LPARAM)&buffer);
1657                 }
1658                 SetFocus(hTabWnd);
1659             }
1660             break;
1661
1662         case WM_COMMAND:
1663             switch(LOWORD(wParam))
1664             {
1665                 case IDC_TABSTOPS:
1666                     {
1667                         HWND hTabWnd = (HWND)lParam;
1668                         HWND hAddWnd = GetDlgItem(hWnd, ID_TAB_ADD);
1669                         HWND hDelWnd = GetDlgItem(hWnd, ID_TAB_DEL);
1670                         HWND hEmptyWnd = GetDlgItem(hWnd, ID_TAB_EMPTY);
1671
1672                         if(GetWindowTextLengthW(hTabWnd))
1673                             EnableWindow(hAddWnd, TRUE);
1674                         else
1675                             EnableWindow(hAddWnd, FALSE);
1676
1677                         if(SendMessageW(hTabWnd, CB_GETCOUNT, 0, 0))
1678                         {
1679                             EnableWindow(hEmptyWnd, TRUE);
1680
1681                             if(SendMessageW(hTabWnd, CB_GETCURSEL, 0, 0) == CB_ERR)
1682                                 EnableWindow(hDelWnd, FALSE);
1683                             else
1684                                 EnableWindow(hDelWnd, TRUE);
1685                         } else
1686                         {
1687                             EnableWindow(hEmptyWnd, FALSE);
1688                         }
1689                     }
1690                     break;
1691
1692                 case ID_TAB_ADD:
1693                     {
1694                         HWND hTabWnd = GetDlgItem(hWnd, IDC_TABSTOPS);
1695                         WCHAR buffer[MAX_STRING_LEN];
1696                         UNIT unit;
1697
1698                         GetWindowTextW(hTabWnd, buffer, MAX_STRING_LEN);
1699                         append_current_units(buffer);
1700
1701                         if(SendMessageW(hTabWnd, CB_FINDSTRINGEXACT, -1, (LPARAM)&buffer) == CB_ERR)
1702                         {
1703                             float number = 0;
1704                             int item_count = SendMessageW(hTabWnd, CB_GETCOUNT, 0, 0);
1705
1706                             if(!number_from_string(buffer, &number, &unit))
1707                             {
1708                                 MessageBoxWithResStringW(hWnd, MAKEINTRESOURCEW(STRING_INVALID_NUMBER),
1709                                              wszAppTitle, MB_OK | MB_ICONINFORMATION);
1710                             } else if (item_count >= MAX_TAB_STOPS) {
1711                                 MessageBoxWithResStringW(hWnd, MAKEINTRESOURCEW(STRING_MAX_TAB_STOPS),
1712                                              wszAppTitle, MB_OK | MB_ICONINFORMATION);
1713                             } else {
1714                                 int i;
1715                                 float next_number = -1;
1716                                 int next_number_in_twips = -1;
1717                                 int insert_number = units_to_twips(unit, number);
1718
1719                                 /* linear search for position to insert the string */
1720                                 for(i = 0; i < item_count; i++)
1721                                 {
1722                                     SendMessageW(hTabWnd, CB_GETLBTEXT, i, (LPARAM)&buffer);
1723                                     number_from_string(buffer, &next_number, &unit);
1724                                     next_number_in_twips = units_to_twips(unit, next_number);
1725                                     if (insert_number <= next_number_in_twips)
1726                                         break;
1727                                 }
1728                                 if (insert_number != next_number_in_twips)
1729                                 {
1730                                     number_with_units(buffer, insert_number);
1731                                     SendMessageW(hTabWnd, CB_INSERTSTRING, i, (LPARAM)&buffer);
1732                                     SetWindowTextW(hTabWnd, 0);
1733                                 }
1734                             }
1735                         }
1736                         SetFocus(hTabWnd);
1737                     }
1738                     break;
1739
1740                 case ID_TAB_DEL:
1741                     {
1742                         HWND hTabWnd = GetDlgItem(hWnd, IDC_TABSTOPS);
1743                         LRESULT ret;
1744                         ret = SendMessageW(hTabWnd, CB_GETCURSEL, 0, 0);
1745                         if(ret != CB_ERR)
1746                             SendMessageW(hTabWnd, CB_DELETESTRING, ret, 0);
1747                     }
1748                     break;
1749
1750                 case ID_TAB_EMPTY:
1751                     {
1752                         HWND hTabWnd = GetDlgItem(hWnd, IDC_TABSTOPS);
1753                         SendMessageW(hTabWnd, CB_RESETCONTENT, 0, 0);
1754                         SetFocus(hTabWnd);
1755                     }
1756                     break;
1757
1758                 case IDOK:
1759                     {
1760                         HWND hTabWnd = GetDlgItem(hWnd, IDC_TABSTOPS);
1761                         int i;
1762                         WCHAR buffer[MAX_STRING_LEN];
1763                         PARAFORMAT pf;
1764                         float number;
1765                         UNIT unit;
1766
1767                         pf.cbSize = sizeof(pf);
1768                         pf.dwMask = PFM_TABSTOPS;
1769
1770                         for(i = 0; SendMessageW(hTabWnd, CB_GETLBTEXT, i,
1771                                                 (LPARAM)&buffer) != CB_ERR &&
1772                                                         i < MAX_TAB_STOPS; i++)
1773                         {
1774                             number_from_string(buffer, &number, &unit);
1775                             pf.rgxTabs[i] = units_to_twips(unit, number);
1776                         }
1777                         pf.cTabCount = i;
1778                         SendMessageW(hEditorWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
1779                     }
1780                     /* Fall through */
1781                 case IDCANCEL:
1782                     EndDialog(hWnd, wParam);
1783                     return TRUE;
1784             }
1785     }
1786     return FALSE;
1787 }
1788
1789 static LRESULT OnCreate( HWND hWnd )
1790 {
1791     HWND hToolBarWnd, hFormatBarWnd,  hReBarWnd, hFontListWnd, hSizeListWnd, hRulerWnd;
1792     HINSTANCE hInstance = GetModuleHandleW(0);
1793     HANDLE hDLL;
1794     TBADDBITMAP ab;
1795     int nStdBitmaps = 0;
1796     REBARINFO rbi;
1797     REBARBANDINFOW rbb;
1798     static const WCHAR wszRichEditDll[] = {'R','I','C','H','E','D','2','0','.','D','L','L','\0'};
1799     static const WCHAR wszRichEditText[] = {'R','i','c','h','E','d','i','t',' ','t','e','x','t','\0'};
1800
1801     CreateStatusWindowW(CCS_NODIVIDER|WS_CHILD|WS_VISIBLE, wszRichEditText, hWnd, IDC_STATUSBAR);
1802
1803     hReBarWnd = CreateWindowExW(WS_EX_TOOLWINDOW, REBARCLASSNAMEW, NULL,
1804       CCS_NODIVIDER|WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|RBS_VARHEIGHT|CCS_TOP,
1805       CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hWnd, (HMENU)IDC_REBAR, hInstance, NULL);
1806
1807     rbi.cbSize = sizeof(rbi);
1808     rbi.fMask = 0;
1809     rbi.himl = NULL;
1810     if(!SendMessageW(hReBarWnd, RB_SETBARINFO, 0, (LPARAM)&rbi))
1811         return -1;
1812
1813     hToolBarWnd = CreateToolbarEx(hReBarWnd, CCS_NOPARENTALIGN|CCS_NOMOVEY|WS_VISIBLE|WS_CHILD|TBSTYLE_TOOLTIPS|BTNS_BUTTON,
1814       IDC_TOOLBAR,
1815       1, hInstance, IDB_TOOLBAR,
1816       NULL, 0,
1817       24, 24, 16, 16, sizeof(TBBUTTON));
1818
1819     ab.hInst = HINST_COMMCTRL;
1820     ab.nID = IDB_STD_SMALL_COLOR;
1821     nStdBitmaps = SendMessageW(hToolBarWnd, TB_ADDBITMAP, 0, (LPARAM)&ab);
1822
1823     AddButton(hToolBarWnd, nStdBitmaps+STD_FILENEW, ID_FILE_NEW);
1824     AddButton(hToolBarWnd, nStdBitmaps+STD_FILEOPEN, ID_FILE_OPEN);
1825     AddButton(hToolBarWnd, nStdBitmaps+STD_FILESAVE, ID_FILE_SAVE);
1826     AddSeparator(hToolBarWnd);
1827     AddButton(hToolBarWnd, nStdBitmaps+STD_PRINT, ID_PRINT_QUICK);
1828     AddButton(hToolBarWnd, nStdBitmaps+STD_PRINTPRE, ID_PREVIEW);
1829     AddSeparator(hToolBarWnd);
1830     AddButton(hToolBarWnd, nStdBitmaps+STD_FIND, ID_FIND);
1831     AddSeparator(hToolBarWnd);
1832     AddButton(hToolBarWnd, nStdBitmaps+STD_CUT, ID_EDIT_CUT);
1833     AddButton(hToolBarWnd, nStdBitmaps+STD_COPY, ID_EDIT_COPY);
1834     AddButton(hToolBarWnd, nStdBitmaps+STD_PASTE, ID_EDIT_PASTE);
1835     AddButton(hToolBarWnd, nStdBitmaps+STD_UNDO, ID_EDIT_UNDO);
1836     AddButton(hToolBarWnd, nStdBitmaps+STD_REDOW, ID_EDIT_REDO);
1837     AddSeparator(hToolBarWnd);
1838     AddButton(hToolBarWnd, 0, ID_DATETIME);
1839
1840     SendMessageW(hToolBarWnd, TB_AUTOSIZE, 0, 0);
1841
1842     rbb.cbSize = REBARBANDINFOW_V6_SIZE;
1843     rbb.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD | RBBIM_STYLE | RBBIM_ID;
1844     rbb.fStyle = RBBS_CHILDEDGE | RBBS_BREAK | RBBS_NOGRIPPER;
1845     rbb.cx = 0;
1846     rbb.hwndChild = hToolBarWnd;
1847     rbb.cxMinChild = 0;
1848     rbb.cyChild = rbb.cyMinChild = HIWORD(SendMessageW(hToolBarWnd, TB_GETBUTTONSIZE, 0, 0));
1849     rbb.wID = BANDID_TOOLBAR;
1850
1851     SendMessageW(hReBarWnd, RB_INSERTBANDW, -1, (LPARAM)&rbb);
1852
1853     hFontListWnd = CreateWindowExW(0, WC_COMBOBOXEXW, NULL,
1854                       WS_BORDER | WS_VISIBLE | WS_CHILD | CBS_DROPDOWN | CBS_SORT,
1855                       0, 0, 200, 150, hReBarWnd, (HMENU)IDC_FONTLIST, hInstance, NULL);
1856
1857     rbb.hwndChild = hFontListWnd;
1858     rbb.cx = 200;
1859     rbb.wID = BANDID_FONTLIST;
1860
1861     SendMessageW(hReBarWnd, RB_INSERTBANDW, -1, (LPARAM)&rbb);
1862
1863     hSizeListWnd = CreateWindowExW(0, WC_COMBOBOXEXW, NULL,
1864                       WS_BORDER | WS_VISIBLE | WS_CHILD | CBS_DROPDOWN,
1865                       0, 0, 50, 150, hReBarWnd, (HMENU)IDC_SIZELIST, hInstance, NULL);
1866
1867     rbb.hwndChild = hSizeListWnd;
1868     rbb.cx = 50;
1869     rbb.fStyle ^= RBBS_BREAK;
1870     rbb.wID = BANDID_SIZELIST;
1871
1872     SendMessageW(hReBarWnd, RB_INSERTBANDW, -1, (LPARAM)&rbb);
1873
1874     hFormatBarWnd = CreateToolbarEx(hReBarWnd,
1875          CCS_NOPARENTALIGN | CCS_NOMOVEY | WS_VISIBLE | TBSTYLE_TOOLTIPS | BTNS_BUTTON,
1876          IDC_FORMATBAR, 8, hInstance, IDB_FORMATBAR, NULL, 0, 16, 16, 16, 16, sizeof(TBBUTTON));
1877
1878     AddButton(hFormatBarWnd, 0, ID_FORMAT_BOLD);
1879     AddButton(hFormatBarWnd, 1, ID_FORMAT_ITALIC);
1880     AddButton(hFormatBarWnd, 2, ID_FORMAT_UNDERLINE);
1881     AddButton(hFormatBarWnd, 3, ID_FORMAT_COLOR);
1882     AddSeparator(hFormatBarWnd);
1883     AddButton(hFormatBarWnd, 4, ID_ALIGN_LEFT);
1884     AddButton(hFormatBarWnd, 5, ID_ALIGN_CENTER);
1885     AddButton(hFormatBarWnd, 6, ID_ALIGN_RIGHT);
1886     AddSeparator(hFormatBarWnd);
1887     AddButton(hFormatBarWnd, 7, ID_BULLET);
1888
1889     SendMessageW(hFormatBarWnd, TB_AUTOSIZE, 0, 0);
1890
1891     rbb.hwndChild = hFormatBarWnd;
1892     rbb.wID = BANDID_FORMATBAR;
1893
1894     SendMessageW(hReBarWnd, RB_INSERTBANDW, -1, (LPARAM)&rbb);
1895
1896     hRulerWnd = CreateWindowExW(0, WC_STATICW, NULL, WS_VISIBLE | WS_CHILD,
1897                                 0, 0, 200, 10, hReBarWnd,  (HMENU)IDC_RULER, hInstance, NULL);
1898
1899
1900     rbb.hwndChild = hRulerWnd;
1901     rbb.wID = BANDID_RULER;
1902     rbb.fStyle |= RBBS_BREAK;
1903
1904     SendMessageW(hReBarWnd, RB_INSERTBANDW, -1, (LPARAM)&rbb);
1905
1906     hDLL = LoadLibraryW(wszRichEditDll);
1907     if(!hDLL)
1908     {
1909         MessageBoxWithResStringW(hWnd, MAKEINTRESOURCEW(STRING_LOAD_RICHED_FAILED), wszAppTitle,
1910                     MB_OK | MB_ICONEXCLAMATION);
1911         PostQuitMessage(1);
1912     }
1913
1914     hEditorWnd = CreateWindowExW(WS_EX_CLIENTEDGE, RICHEDIT_CLASS20W, NULL,
1915       WS_CHILD|WS_VISIBLE|ES_SELECTIONBAR|ES_MULTILINE|ES_AUTOVSCROLL
1916       |ES_WANTRETURN|WS_VSCROLL|ES_NOHIDESEL|WS_HSCROLL,
1917       0, 0, 1000, 100, hWnd, (HMENU)IDC_EDITOR, hInstance, NULL);
1918
1919     if (!hEditorWnd)
1920     {
1921         fprintf(stderr, "Error code %u\n", GetLastError());
1922         return -1;
1923     }
1924     assert(hEditorWnd);
1925
1926     setup_richedit_olecallback(hEditorWnd);
1927     SetFocus(hEditorWnd);
1928     SendMessageW(hEditorWnd, EM_SETEVENTMASK, 0, ENM_SELCHANGE);
1929
1930     set_default_font();
1931
1932     populate_font_list(hFontListWnd);
1933     populate_size_list(hSizeListWnd);
1934     DoLoadStrings();
1935     SendMessageW(hEditorWnd, EM_SETMODIFY, FALSE, 0);
1936
1937     ID_FINDMSGSTRING = RegisterWindowMessageW(FINDMSGSTRINGW);
1938
1939     registry_read_filelist(hWnd);
1940     registry_read_formatopts_all(barState, wordWrap);
1941     registry_read_options();
1942     DragAcceptFiles(hWnd, TRUE);
1943
1944     return 0;
1945 }
1946
1947 static LRESULT OnUser( HWND hWnd )
1948 {
1949     HWND hwndEditor = GetDlgItem(hWnd, IDC_EDITOR);
1950     HWND hwndReBar = GetDlgItem(hWnd, IDC_REBAR);
1951     HWND hwndToolBar = GetDlgItem(hwndReBar, IDC_TOOLBAR);
1952     HWND hwndFormatBar = GetDlgItem(hwndReBar, IDC_FORMATBAR);
1953     int from, to;
1954     CHARFORMAT2W fmt;
1955     PARAFORMAT2 pf;
1956     GETTEXTLENGTHEX gt;
1957
1958     ZeroMemory(&fmt, sizeof(fmt));
1959     fmt.cbSize = sizeof(fmt);
1960
1961     ZeroMemory(&pf, sizeof(pf));
1962     pf.cbSize = sizeof(pf);
1963
1964     gt.flags = GTL_NUMCHARS;
1965     gt.codepage = 1200;
1966
1967     SendMessageW(hwndToolBar, TB_ENABLEBUTTON, ID_FIND,
1968                  SendMessageW(hwndEditor, EM_GETTEXTLENGTHEX, (WPARAM)&gt, 0) ? 1 : 0);
1969
1970     SendMessageW(hwndEditor, EM_GETCHARFORMAT, TRUE, (LPARAM)&fmt);
1971
1972     SendMessageW(hwndEditor, EM_GETSEL, (WPARAM)&from, (LPARAM)&to);
1973     SendMessageW(hwndToolBar, TB_ENABLEBUTTON, ID_EDIT_UNDO,
1974       SendMessageW(hwndEditor, EM_CANUNDO, 0, 0));
1975     SendMessageW(hwndToolBar, TB_ENABLEBUTTON, ID_EDIT_REDO,
1976       SendMessageW(hwndEditor, EM_CANREDO, 0, 0));
1977     SendMessageW(hwndToolBar, TB_ENABLEBUTTON, ID_EDIT_CUT, from == to ? 0 : 1);
1978     SendMessageW(hwndToolBar, TB_ENABLEBUTTON, ID_EDIT_COPY, from == to ? 0 : 1);
1979
1980     SendMessageW(hwndFormatBar, TB_CHECKBUTTON, ID_FORMAT_BOLD, (fmt.dwMask & CFM_BOLD) &&
1981             (fmt.dwEffects & CFE_BOLD));
1982     SendMessageW(hwndFormatBar, TB_INDETERMINATE, ID_FORMAT_BOLD, !(fmt.dwMask & CFM_BOLD));
1983     SendMessageW(hwndFormatBar, TB_CHECKBUTTON, ID_FORMAT_ITALIC, (fmt.dwMask & CFM_ITALIC) &&
1984             (fmt.dwEffects & CFE_ITALIC));
1985     SendMessageW(hwndFormatBar, TB_INDETERMINATE, ID_FORMAT_ITALIC, !(fmt.dwMask & CFM_ITALIC));
1986     SendMessageW(hwndFormatBar, TB_CHECKBUTTON, ID_FORMAT_UNDERLINE, (fmt.dwMask & CFM_UNDERLINE) &&
1987             (fmt.dwEffects & CFE_UNDERLINE));
1988     SendMessageW(hwndFormatBar, TB_INDETERMINATE, ID_FORMAT_UNDERLINE, !(fmt.dwMask & CFM_UNDERLINE));
1989
1990     SendMessageW(hwndEditor, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
1991     SendMessageW(hwndFormatBar, TB_CHECKBUTTON, ID_ALIGN_LEFT, (pf.wAlignment == PFA_LEFT));
1992     SendMessageW(hwndFormatBar, TB_CHECKBUTTON, ID_ALIGN_CENTER, (pf.wAlignment == PFA_CENTER));
1993     SendMessageW(hwndFormatBar, TB_CHECKBUTTON, ID_ALIGN_RIGHT, (pf.wAlignment == PFA_RIGHT));
1994
1995     SendMessageW(hwndFormatBar, TB_CHECKBUTTON, ID_BULLET, (pf.wNumbering & PFN_BULLET));
1996     return 0;
1997 }
1998
1999 static LRESULT OnNotify( HWND hWnd, LPARAM lParam)
2000 {
2001     HWND hwndEditor = GetDlgItem(hWnd, IDC_EDITOR);
2002     HWND hwndReBar = GetDlgItem(hWnd, IDC_REBAR);
2003     NMHDR *pHdr = (NMHDR *)lParam;
2004     HWND hwndFontList = GetDlgItem(hwndReBar, IDC_FONTLIST);
2005     HWND hwndSizeList = GetDlgItem(hwndReBar, IDC_SIZELIST);
2006
2007     if (pHdr->hwndFrom == hwndFontList || pHdr->hwndFrom == hwndSizeList)
2008     {
2009         if (pHdr->code == CBEN_ENDEDITW)
2010         {
2011             NMCBEENDEDITW *endEdit = (NMCBEENDEDITW *)lParam;
2012             if(pHdr->hwndFrom == hwndFontList)
2013             {
2014                 on_fontlist_modified(endEdit->szText);
2015             } else if (pHdr->hwndFrom == hwndSizeList)
2016             {
2017                 on_sizelist_modified(hwndFontList,endEdit->szText);
2018             }
2019         }
2020         return 0;
2021     }
2022
2023     if (pHdr->hwndFrom != hwndEditor)
2024         return 0;
2025
2026     if (pHdr->code == EN_SELCHANGE)
2027     {
2028         SELCHANGE *pSC = (SELCHANGE *)lParam;
2029         char buf[128];
2030
2031         update_font_list();
2032
2033         sprintf( buf,"selection = %d..%d, line count=%ld",
2034                  pSC->chrg.cpMin, pSC->chrg.cpMax,
2035                 SendMessageW(hwndEditor, EM_GETLINECOUNT, 0, 0));
2036         SetWindowTextA(GetDlgItem(hWnd, IDC_STATUSBAR), buf);
2037         SendMessageW(hWnd, WM_USER, 0, 0);
2038         return 1;
2039     }
2040     return 0;
2041 }
2042
2043 /* Copied from dlls/comdlg32/fontdlg.c */
2044 static const COLORREF textcolors[]=
2045 {
2046     0x00000000L,0x00000080L,0x00008000L,0x00008080L,
2047     0x00800000L,0x00800080L,0x00808000L,0x00808080L,
2048     0x00c0c0c0L,0x000000ffL,0x0000ff00L,0x0000ffffL,
2049     0x00ff0000L,0x00ff00ffL,0x00ffff00L,0x00FFFFFFL
2050 };
2051
2052 static LRESULT OnCommand( HWND hWnd, WPARAM wParam, LPARAM lParam)
2053 {
2054     HWND hwndEditor = GetDlgItem(hWnd, IDC_EDITOR);
2055     static FINDREPLACEW findreplace;
2056
2057     if ((HWND)lParam == hwndEditor)
2058         return 0;
2059
2060     switch(LOWORD(wParam))
2061     {
2062
2063     case ID_FILE_EXIT:
2064         PostMessageW(hWnd, WM_CLOSE, 0, 0);
2065         break;
2066
2067     case ID_FILE_NEW:
2068         {
2069             HINSTANCE hInstance = GetModuleHandleW(0);
2070             int ret = DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_NEWFILE), hWnd, newfile_proc);
2071
2072             if(ret != ID_NEWFILE_ABORT)
2073             {
2074                 if(prompt_save_changes())
2075                 {
2076                     SETTEXTEX st;
2077
2078                     set_caption(NULL);
2079                     wszFileName[0] = '\0';
2080
2081                     clear_formatting();
2082
2083                     st.flags = ST_DEFAULT;
2084                     st.codepage = 1200;
2085                     SendMessageW(hEditorWnd, EM_SETTEXTEX, (WPARAM)&st, 0);
2086
2087                     SendMessageW(hEditorWnd, EM_SETMODIFY, FALSE, 0);
2088                     set_fileformat(ret);
2089                     update_font_list();
2090                 }
2091             }
2092         }
2093         break;
2094
2095     case ID_FILE_OPEN:
2096         DialogOpenFile();
2097         break;
2098
2099     case ID_FILE_SAVE:
2100         if(wszFileName[0])
2101         {
2102             DoSaveFile(wszFileName, fileFormat);
2103             break;
2104         }
2105         /* Fall through */
2106
2107     case ID_FILE_SAVEAS:
2108         DialogSaveFile();
2109         break;
2110
2111     case ID_FILE_RECENT1:
2112     case ID_FILE_RECENT2:
2113     case ID_FILE_RECENT3:
2114     case ID_FILE_RECENT4:
2115         {
2116             HMENU hMenu = GetMenu(hWnd);
2117             MENUITEMINFOW mi;
2118
2119             mi.cbSize = sizeof(MENUITEMINFOW);
2120             mi.fMask = MIIM_DATA;
2121             if(GetMenuItemInfoW(hMenu, LOWORD(wParam), FALSE, &mi))
2122                 DoOpenFile((LPWSTR)mi.dwItemData);
2123         }
2124         break;
2125
2126     case ID_FIND:
2127         dialog_find(&findreplace, FALSE);
2128         break;
2129
2130     case ID_FIND_NEXT:
2131         handle_findmsg(&findreplace);
2132         break;
2133
2134     case ID_REPLACE:
2135         dialog_find(&findreplace, TRUE);
2136         break;
2137
2138     case ID_FONTSETTINGS:
2139         dialog_choose_font();
2140         break;
2141
2142     case ID_PRINT:
2143         dialog_print(hWnd, wszFileName);
2144         target_device(hMainWnd, wordWrap[reg_formatindex(fileFormat)]);
2145         break;
2146
2147     case ID_PRINT_QUICK:
2148         print_quick(hMainWnd, wszFileName);
2149         target_device(hMainWnd, wordWrap[reg_formatindex(fileFormat)]);
2150         break;
2151
2152     case ID_PREVIEW:
2153         {
2154             int index = reg_formatindex(fileFormat);
2155             DWORD tmp = barState[index];
2156             barState[index] = 1 << BANDID_STATUSBAR;
2157             set_bar_states();
2158             barState[index] = tmp;
2159             ShowWindow(hEditorWnd, FALSE);
2160
2161             init_preview(hWnd, wszFileName);
2162
2163             SetMenu(hWnd, NULL);
2164             InvalidateRect(0, 0, TRUE);
2165         }
2166         break;
2167
2168     case ID_PRINTSETUP:
2169         dialog_printsetup(hWnd);
2170         target_device(hMainWnd, wordWrap[reg_formatindex(fileFormat)]);
2171         break;
2172
2173     case ID_FORMAT_BOLD:
2174     case ID_FORMAT_ITALIC:
2175     case ID_FORMAT_UNDERLINE:
2176         {
2177         CHARFORMAT2W fmt;
2178         int effects = CFE_BOLD;
2179
2180         ZeroMemory(&fmt, sizeof(fmt));
2181         fmt.cbSize = sizeof(fmt);
2182         SendMessageW(hwndEditor, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt);
2183
2184         fmt.dwMask = CFM_BOLD;
2185
2186         if (LOWORD(wParam) == ID_FORMAT_ITALIC)
2187         {
2188             effects = CFE_ITALIC;
2189             fmt.dwMask = CFM_ITALIC;
2190         } else if (LOWORD(wParam) == ID_FORMAT_UNDERLINE)
2191         {
2192             effects = CFE_UNDERLINE;
2193             fmt.dwMask = CFM_UNDERLINE;
2194         }
2195
2196         fmt.dwEffects ^= effects;
2197
2198         SendMessageW(hwndEditor, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt);
2199         break;
2200         }
2201
2202     case ID_FORMAT_COLOR:
2203     {
2204         HWND hReBarWnd = GetDlgItem(hWnd, IDC_REBAR);
2205         HWND hFormatBarWnd = GetDlgItem(hReBarWnd, IDC_FORMATBAR);
2206         HMENU hPop;
2207         RECT itemrc;
2208         POINT pt;
2209         int mid;
2210         int itemidx = SendMessageW(hFormatBarWnd, TB_COMMANDTOINDEX, ID_FORMAT_COLOR, 0);
2211
2212         SendMessageW(hFormatBarWnd, TB_GETITEMRECT, itemidx, (LPARAM)&itemrc);
2213         pt.x = itemrc.left;
2214         pt.y = itemrc.bottom;
2215         ClientToScreen(hFormatBarWnd, &pt);
2216         hPop = GetSubMenu(hColorPopupMenu, 0);
2217         mid = TrackPopupMenu(hPop, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON |
2218                                    TPM_RETURNCMD | TPM_NONOTIFY,
2219                              pt.x, pt.y, 0, hWnd, 0);
2220         if (mid >= ID_COLOR_FIRST && mid <= ID_COLOR_AUTOMATIC)
2221         {
2222             CHARFORMAT2W fmt;
2223
2224             ZeroMemory(&fmt, sizeof(fmt));
2225             fmt.cbSize = sizeof(fmt);
2226             SendMessageW(hwndEditor, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt);
2227
2228             fmt.dwMask = CFM_COLOR;
2229
2230             if (mid < ID_COLOR_AUTOMATIC) {
2231                 fmt.crTextColor = textcolors[mid - ID_COLOR_FIRST];
2232                 fmt.dwEffects &= ~CFE_AUTOCOLOR;
2233             } else {
2234                 fmt.dwEffects |= CFE_AUTOCOLOR;
2235             }
2236
2237             SendMessageW(hwndEditor, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt);
2238         }
2239         break;
2240     }
2241
2242     case ID_EDIT_CUT:
2243         PostMessageW(hwndEditor, WM_CUT, 0, 0);
2244         break;
2245
2246     case ID_EDIT_COPY:
2247         PostMessageW(hwndEditor, WM_COPY, 0, 0);
2248         break;
2249
2250     case ID_EDIT_PASTE:
2251         PostMessageW(hwndEditor, WM_PASTE, 0, 0);
2252         break;
2253
2254     case ID_EDIT_CLEAR:
2255         PostMessageW(hwndEditor, WM_CLEAR, 0, 0);
2256         break;
2257
2258     case ID_EDIT_SELECTALL:
2259         {
2260         CHARRANGE range = {0, -1};
2261         SendMessageW(hwndEditor, EM_EXSETSEL, 0, (LPARAM)&range);
2262         /* SendMessage(hwndEditor, EM_SETSEL, 0, -1); */
2263         return 0;
2264         }
2265
2266     case ID_EDIT_GETTEXT:
2267         {
2268         int nLen = GetWindowTextLengthW(hwndEditor);
2269         LPWSTR data = HeapAlloc( GetProcessHeap(), 0, (nLen+1)*sizeof(WCHAR) );
2270         TEXTRANGEW tr;
2271
2272         GetWindowTextW(hwndEditor, data, nLen+1);
2273         MessageBoxW(NULL, data, wszAppTitle, MB_OK);
2274
2275         HeapFree( GetProcessHeap(), 0, data);
2276         data = HeapAlloc(GetProcessHeap(), 0, (nLen+1)*sizeof(WCHAR));
2277         tr.chrg.cpMin = 0;
2278         tr.chrg.cpMax = nLen;
2279         tr.lpstrText = data;
2280         SendMessageW(hwndEditor, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
2281         MessageBoxW(NULL, data, wszAppTitle, MB_OK);
2282         HeapFree( GetProcessHeap(), 0, data );
2283
2284         /* SendMessage(hwndEditor, EM_SETSEL, 0, -1); */
2285         return 0;
2286         }
2287
2288     case ID_EDIT_CHARFORMAT:
2289     case ID_EDIT_DEFCHARFORMAT:
2290         {
2291         CHARFORMAT2W cf;
2292
2293         ZeroMemory(&cf, sizeof(cf));
2294         cf.cbSize = sizeof(cf);
2295         cf.dwMask = 0;
2296         SendMessageW(hwndEditor, EM_GETCHARFORMAT,
2297                      LOWORD(wParam) == ID_EDIT_CHARFORMAT, (LPARAM)&cf);
2298         return 0;
2299         }
2300
2301     case ID_EDIT_PARAFORMAT:
2302         {
2303         PARAFORMAT2 pf;
2304         ZeroMemory(&pf, sizeof(pf));
2305         pf.cbSize = sizeof(pf);
2306         SendMessageW(hwndEditor, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
2307         return 0;
2308         }
2309
2310     case ID_EDIT_SELECTIONINFO:
2311         {
2312         CHARRANGE range = {0, -1};
2313         char buf[128];
2314         WCHAR *data = NULL;
2315
2316         SendMessageW(hwndEditor, EM_EXGETSEL, 0, (LPARAM)&range);
2317         data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data) * (range.cpMax-range.cpMin+1));
2318         SendMessageW(hwndEditor, EM_GETSELTEXT, 0, (LPARAM)data);
2319         sprintf(buf, "Start = %d, End = %d", range.cpMin, range.cpMax);
2320         MessageBoxA(hWnd, buf, "Editor", MB_OK);
2321         MessageBoxW(hWnd, data, wszAppTitle, MB_OK);
2322         HeapFree( GetProcessHeap(), 0, data);
2323         /* SendMessage(hwndEditor, EM_SETSEL, 0, -1); */
2324         return 0;
2325         }
2326
2327     case ID_EDIT_READONLY:
2328         {
2329         LONG nStyle = GetWindowLongW(hwndEditor, GWL_STYLE);
2330         if (nStyle & ES_READONLY)
2331             SendMessageW(hwndEditor, EM_SETREADONLY, 0, 0);
2332         else
2333             SendMessageW(hwndEditor, EM_SETREADONLY, 1, 0);
2334         return 0;
2335         }
2336
2337     case ID_EDIT_MODIFIED:
2338         if (SendMessageW(hwndEditor, EM_GETMODIFY, 0, 0))
2339             SendMessageW(hwndEditor, EM_SETMODIFY, 0, 0);
2340         else
2341             SendMessageW(hwndEditor, EM_SETMODIFY, 1, 0);
2342         return 0;
2343
2344     case ID_EDIT_UNDO:
2345         SendMessageW(hwndEditor, EM_UNDO, 0, 0);
2346         return 0;
2347
2348     case ID_EDIT_REDO:
2349         SendMessageW(hwndEditor, EM_REDO, 0, 0);
2350         return 0;
2351
2352     case ID_BULLET:
2353         {
2354             PARAFORMAT pf;
2355
2356             pf.cbSize = sizeof(pf);
2357             pf.dwMask = PFM_NUMBERING;
2358             SendMessageW(hwndEditor, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
2359
2360             pf.dwMask |=  PFM_OFFSET;
2361
2362             if(pf.wNumbering == PFN_BULLET)
2363             {
2364                 pf.wNumbering = 0;
2365                 pf.dxOffset = 0;
2366             } else
2367             {
2368                 pf.wNumbering = PFN_BULLET;
2369                 pf.dxOffset = 720;
2370             }
2371
2372             SendMessageW(hwndEditor, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
2373         }
2374         break;
2375
2376     case ID_ALIGN_LEFT:
2377     case ID_ALIGN_CENTER:
2378     case ID_ALIGN_RIGHT:
2379         {
2380         PARAFORMAT2 pf;
2381
2382         pf.cbSize = sizeof(pf);
2383         pf.dwMask = PFM_ALIGNMENT;
2384         switch(LOWORD(wParam)) {
2385         case ID_ALIGN_LEFT: pf.wAlignment = PFA_LEFT; break;
2386         case ID_ALIGN_CENTER: pf.wAlignment = PFA_CENTER; break;
2387         case ID_ALIGN_RIGHT: pf.wAlignment = PFA_RIGHT; break;
2388         }
2389         SendMessageW(hwndEditor, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
2390         break;
2391         }
2392
2393     case ID_BACK_1:
2394         SendMessageW(hwndEditor, EM_SETBKGNDCOLOR, 1, 0);
2395         break;
2396
2397     case ID_BACK_2:
2398         SendMessageW(hwndEditor, EM_SETBKGNDCOLOR, 0, RGB(255,255,192));
2399         break;
2400
2401     case ID_TOGGLE_TOOLBAR:
2402         set_toolbar_state(BANDID_TOOLBAR, !is_bar_visible(BANDID_TOOLBAR));
2403         update_window();
2404         break;
2405
2406     case ID_TOGGLE_FORMATBAR:
2407         set_toolbar_state(BANDID_FONTLIST, !is_bar_visible(BANDID_FORMATBAR));
2408         set_toolbar_state(BANDID_SIZELIST, !is_bar_visible(BANDID_FORMATBAR));
2409         set_toolbar_state(BANDID_FORMATBAR, !is_bar_visible(BANDID_FORMATBAR));
2410         update_window();
2411         break;
2412
2413     case ID_TOGGLE_STATUSBAR:
2414         set_statusbar_state(!is_bar_visible(BANDID_STATUSBAR));
2415         update_window();
2416         break;
2417
2418     case ID_TOGGLE_RULER:
2419         set_toolbar_state(BANDID_RULER, !is_bar_visible(BANDID_RULER));
2420         update_window();
2421         break;
2422
2423     case ID_DATETIME:
2424         DialogBoxW(GetModuleHandleW(0), MAKEINTRESOURCEW(IDD_DATETIME), hWnd, datetime_proc);
2425         break;
2426
2427     case ID_PARAFORMAT:
2428         DialogBoxW(GetModuleHandleW(0), MAKEINTRESOURCEW(IDD_PARAFORMAT), hWnd, paraformat_proc);
2429         break;
2430
2431     case ID_TABSTOPS:
2432         DialogBoxW(GetModuleHandleW(0), MAKEINTRESOURCEW(IDD_TABSTOPS), hWnd, tabstops_proc);
2433         break;
2434
2435     case ID_ABOUT:
2436         dialog_about();
2437         break;
2438
2439     case ID_VIEWPROPERTIES:
2440         dialog_viewproperties();
2441         break;
2442
2443     case IDC_FONTLIST:
2444         if (HIWORD(wParam) == CBN_SELENDOK)
2445         {
2446             WCHAR buffer[LF_FACESIZE];
2447             HWND hwndFontList = (HWND)lParam;
2448             get_comboexlist_selection(hwndFontList, buffer, LF_FACESIZE);
2449             on_fontlist_modified(buffer);
2450         }
2451         break;
2452
2453     case IDC_SIZELIST:
2454         if (HIWORD(wParam) == CBN_SELENDOK)
2455         {
2456             WCHAR buffer[MAX_STRING_LEN+1];
2457             HWND hwndSizeList = (HWND)lParam;
2458             get_comboexlist_selection(hwndSizeList, buffer, MAX_STRING_LEN+1);
2459             on_sizelist_modified(hwndSizeList, buffer);
2460         }
2461         break;
2462
2463     default:
2464         SendMessageW(hwndEditor, WM_COMMAND, wParam, lParam);
2465         break;
2466     }
2467     return 0;
2468 }
2469
2470 static LRESULT OnInitPopupMenu( HWND hWnd, WPARAM wParam )
2471 {
2472     HMENU hMenu = (HMENU)wParam;
2473     HWND hwndEditor = GetDlgItem(hWnd, IDC_EDITOR);
2474     HWND hwndStatus = GetDlgItem(hWnd, IDC_STATUSBAR);
2475     PARAFORMAT pf;
2476     int nAlignment = -1;
2477     int selFrom, selTo;
2478     GETTEXTLENGTHEX gt;
2479     LRESULT textLength;
2480     MENUITEMINFOW mi;
2481
2482     SendMessageW(hEditorWnd, EM_GETSEL, (WPARAM)&selFrom, (LPARAM)&selTo);
2483     EnableMenuItem(hMenu, ID_EDIT_COPY, MF_BYCOMMAND|(selFrom == selTo) ? MF_GRAYED : MF_ENABLED);
2484     EnableMenuItem(hMenu, ID_EDIT_CUT, MF_BYCOMMAND|(selFrom == selTo) ? MF_GRAYED : MF_ENABLED);
2485
2486     pf.cbSize = sizeof(PARAFORMAT);
2487     SendMessageW(hwndEditor, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
2488     CheckMenuItem(hMenu, ID_EDIT_READONLY,
2489       MF_BYCOMMAND|(GetWindowLongW(hwndEditor, GWL_STYLE)&ES_READONLY ? MF_CHECKED : MF_UNCHECKED));
2490     CheckMenuItem(hMenu, ID_EDIT_MODIFIED,
2491       MF_BYCOMMAND|(SendMessageW(hwndEditor, EM_GETMODIFY, 0, 0) ? MF_CHECKED : MF_UNCHECKED));
2492     if (pf.dwMask & PFM_ALIGNMENT)
2493         nAlignment = pf.wAlignment;
2494     CheckMenuItem(hMenu, ID_ALIGN_LEFT, MF_BYCOMMAND|(nAlignment == PFA_LEFT) ?
2495             MF_CHECKED : MF_UNCHECKED);
2496     CheckMenuItem(hMenu, ID_ALIGN_CENTER, MF_BYCOMMAND|(nAlignment == PFA_CENTER) ?
2497             MF_CHECKED : MF_UNCHECKED);
2498     CheckMenuItem(hMenu, ID_ALIGN_RIGHT, MF_BYCOMMAND|(nAlignment == PFA_RIGHT) ?
2499             MF_CHECKED : MF_UNCHECKED);
2500     CheckMenuItem(hMenu, ID_BULLET, MF_BYCOMMAND | ((pf.wNumbering == PFN_BULLET) ?
2501             MF_CHECKED : MF_UNCHECKED));
2502     EnableMenuItem(hMenu, ID_EDIT_UNDO, MF_BYCOMMAND|(SendMessageW(hwndEditor, EM_CANUNDO, 0, 0)) ?
2503             MF_ENABLED : MF_GRAYED);
2504     EnableMenuItem(hMenu, ID_EDIT_REDO, MF_BYCOMMAND|(SendMessageW(hwndEditor, EM_CANREDO, 0, 0)) ?
2505             MF_ENABLED : MF_GRAYED);
2506
2507     CheckMenuItem(hMenu, ID_TOGGLE_TOOLBAR, MF_BYCOMMAND|(is_bar_visible(BANDID_TOOLBAR)) ?
2508             MF_CHECKED : MF_UNCHECKED);
2509
2510     CheckMenuItem(hMenu, ID_TOGGLE_FORMATBAR, MF_BYCOMMAND|(is_bar_visible(BANDID_FORMATBAR)) ?
2511             MF_CHECKED : MF_UNCHECKED);
2512
2513     CheckMenuItem(hMenu, ID_TOGGLE_STATUSBAR, MF_BYCOMMAND|IsWindowVisible(hwndStatus) ?
2514             MF_CHECKED : MF_UNCHECKED);
2515
2516     CheckMenuItem(hMenu, ID_TOGGLE_RULER, MF_BYCOMMAND|(is_bar_visible(BANDID_RULER)) ? MF_CHECKED : MF_UNCHECKED);
2517
2518     gt.flags = GTL_NUMCHARS;
2519     gt.codepage = 1200;
2520     textLength = SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, 0);
2521     EnableMenuItem(hMenu, ID_FIND, MF_BYCOMMAND|(textLength ? MF_ENABLED : MF_GRAYED));
2522
2523     mi.cbSize = sizeof(mi);
2524     mi.fMask = MIIM_DATA;
2525
2526     GetMenuItemInfoW(hMenu, ID_FIND_NEXT, FALSE, &mi);
2527
2528     EnableMenuItem(hMenu, ID_FIND_NEXT, MF_BYCOMMAND|((textLength && mi.dwItemData) ?
2529                    MF_ENABLED : MF_GRAYED));
2530
2531     EnableMenuItem(hMenu, ID_REPLACE, MF_BYCOMMAND|(textLength ? MF_ENABLED : MF_GRAYED));
2532
2533     return 0;
2534 }
2535
2536 static LRESULT OnSize( HWND hWnd, WPARAM wParam, LPARAM lParam )
2537 {
2538     int nStatusSize = 0;
2539     RECT rc;
2540     HWND hwndEditor = preview_isactive() ? GetDlgItem(hWnd, IDC_PREVIEW) : GetDlgItem(hWnd, IDC_EDITOR);
2541     HWND hwndStatusBar = GetDlgItem(hWnd, IDC_STATUSBAR);
2542     HWND hwndReBar = GetDlgItem(hWnd, IDC_REBAR);
2543     HWND hRulerWnd = GetDlgItem(hwndReBar, IDC_RULER);
2544     int rebarHeight = 0;
2545
2546     if (hwndStatusBar)
2547     {
2548         SendMessageW(hwndStatusBar, WM_SIZE, 0, 0);
2549         if (IsWindowVisible(hwndStatusBar))
2550         {
2551             GetClientRect(hwndStatusBar, &rc);
2552             nStatusSize = rc.bottom - rc.top;
2553         } else
2554         {
2555             nStatusSize = 0;
2556         }
2557     }
2558     if (hwndReBar)
2559     {
2560         rebarHeight = SendMessageW(hwndReBar, RB_GETBARHEIGHT, 0, 0);
2561
2562         MoveWindow(hwndReBar, 0, 0, LOWORD(lParam), rebarHeight, TRUE);
2563     }
2564     if (hwndEditor)
2565     {
2566         GetClientRect(hWnd, &rc);
2567         MoveWindow(hwndEditor, 0, rebarHeight, rc.right, rc.bottom-nStatusSize-rebarHeight, TRUE);
2568     }
2569
2570     redraw_ruler(hRulerWnd);
2571
2572     return DefWindowProcW(hWnd, WM_SIZE, wParam, lParam);
2573 }
2574
2575 static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2576 {
2577     if(msg == ID_FINDMSGSTRING)
2578         return handle_findmsg((LPFINDREPLACEW)lParam);
2579
2580     switch(msg)
2581     {
2582     case WM_CREATE:
2583         return OnCreate( hWnd );
2584
2585     case WM_USER:
2586         return OnUser( hWnd );
2587
2588     case WM_NOTIFY:
2589         return OnNotify( hWnd, lParam );
2590
2591     case WM_COMMAND:
2592         if(preview_isactive())
2593         {
2594             return preview_command( hWnd, wParam );
2595         }
2596
2597         return OnCommand( hWnd, wParam, lParam );
2598
2599     case WM_DESTROY:
2600         PostQuitMessage(0);
2601         break;
2602
2603     case WM_CLOSE:
2604         if(preview_isactive())
2605         {
2606             preview_exit(hWnd);
2607         } else if(prompt_save_changes())
2608         {
2609             registry_set_options(hMainWnd);
2610             registry_set_formatopts_all(barState, wordWrap);
2611             PostQuitMessage(0);
2612         }
2613         break;
2614
2615     case WM_ACTIVATE:
2616         if (LOWORD(wParam))
2617             SetFocus(GetDlgItem(hWnd, IDC_EDITOR));
2618         return 0;
2619
2620     case WM_INITMENUPOPUP:
2621         return OnInitPopupMenu( hWnd, wParam );
2622
2623     case WM_SIZE:
2624         return OnSize( hWnd, wParam, lParam );
2625
2626     case WM_CONTEXTMENU:
2627         return DefWindowProcW(hWnd, msg, wParam, lParam);
2628
2629     case WM_DROPFILES:
2630         {
2631             WCHAR file[MAX_PATH];
2632             DragQueryFileW((HDROP)wParam, 0, file, MAX_PATH);
2633             DragFinish((HDROP)wParam);
2634
2635             if(prompt_save_changes())
2636                 DoOpenFile(file);
2637         }
2638         break;
2639     case WM_PAINT:
2640         if(!preview_isactive())
2641             return DefWindowProcW(hWnd, msg, wParam, lParam);
2642
2643     default:
2644         return DefWindowProcW(hWnd, msg, wParam, lParam);
2645     }
2646
2647     return 0;
2648 }
2649
2650 int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hOldInstance, LPSTR szCmdParagraph, int nCmdShow)
2651 {
2652     INITCOMMONCONTROLSEX classes = {8, ICC_BAR_CLASSES|ICC_COOL_CLASSES|ICC_USEREX_CLASSES};
2653     HACCEL hAccel;
2654     WNDCLASSEXW wc;
2655     MSG msg;
2656     RECT rc;
2657     UINT_PTR hPrevRulerProc;
2658     HWND hRulerWnd;
2659     POINTL EditPoint;
2660     DWORD bMaximized;
2661     static const WCHAR wszAccelTable[] = {'M','A','I','N','A','C','C','E','L',
2662                                           'T','A','B','L','E','\0'};
2663
2664     InitCommonControlsEx(&classes);
2665
2666     hAccel = LoadAcceleratorsW(hInstance, wszAccelTable);
2667
2668     wc.cbSize = sizeof(wc);
2669     wc.style = 0;
2670     wc.lpfnWndProc = WndProc;
2671     wc.cbClsExtra = 0;
2672     wc.cbWndExtra = 4;
2673     wc.hInstance = hInstance;
2674     wc.hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_WORDPAD));
2675     wc.hIconSm = LoadImageW(hInstance, MAKEINTRESOURCEW(IDI_WORDPAD), IMAGE_ICON,
2676                             GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
2677     wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_IBEAM);
2678     wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
2679     wc.lpszMenuName = MAKEINTRESOURCEW(IDM_MAINMENU);
2680     wc.lpszClassName = wszMainWndClass;
2681     RegisterClassExW(&wc);
2682
2683     wc.style = 0;
2684     wc.lpfnWndProc = preview_proc;
2685     wc.cbClsExtra = 0;
2686     wc.cbWndExtra = 0;
2687     wc.hInstance = hInstance;
2688     wc.hIcon = NULL;
2689     wc.hIconSm = NULL;
2690     wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_IBEAM);
2691     wc.hbrBackground = NULL;
2692     wc.lpszMenuName = NULL;
2693     wc.lpszClassName = wszPreviewWndClass;
2694     RegisterClassExW(&wc);
2695
2696     registry_read_winrect(&rc);
2697     hMainWnd = CreateWindowExW(0, wszMainWndClass, wszAppTitle, WS_CLIPCHILDREN|WS_OVERLAPPEDWINDOW,
2698       rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, hInstance, NULL);
2699     registry_read_maximized(&bMaximized);
2700     if ((nCmdShow == SW_SHOWNORMAL || nCmdShow == SW_SHOWDEFAULT)
2701              && bMaximized)
2702         nCmdShow = SW_SHOWMAXIMIZED;
2703     ShowWindow(hMainWnd, nCmdShow);
2704
2705     set_caption(NULL);
2706     set_bar_states();
2707     set_fileformat(SF_RTF);
2708     hColorPopupMenu = LoadMenuW(hInstance, MAKEINTRESOURCEW(IDM_COLOR_POPUP));
2709     get_default_printer_opts();
2710     target_device(hMainWnd, wordWrap[reg_formatindex(fileFormat)]);
2711
2712     hRulerWnd = GetDlgItem(GetDlgItem(hMainWnd, IDC_REBAR), IDC_RULER);
2713     SendMessageW(GetDlgItem(hMainWnd, IDC_EDITOR), EM_POSFROMCHAR, (WPARAM)&EditPoint, 0);
2714     hPrevRulerProc = SetWindowLongPtrW(hRulerWnd, GWLP_WNDPROC, (UINT_PTR)ruler_proc);
2715     SendMessageW(hRulerWnd, WM_USER, (WPARAM)&EditPoint, hPrevRulerProc);
2716
2717     HandleCommandLine(GetCommandLineW());
2718
2719     while(GetMessageW(&msg,0,0,0))
2720     {
2721         if (IsDialogMessageW(hFindWnd, &msg))
2722             continue;
2723
2724         if (TranslateAcceleratorW(hMainWnd, hAccel, &msg))
2725             continue;
2726         TranslateMessage(&msg);
2727         DispatchMessageW(&msg);
2728         if (!PeekMessageW(&msg, 0, 0, 0, PM_NOREMOVE))
2729             SendMessageW(hMainWnd, WM_USER, 0, 0);
2730     }
2731
2732     return 0;
2733 }