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(¶ms); 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)>, 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)>, 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)>, (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)>, 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)>, 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