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