Minor changes for ATAPI Srb Functions
[reactos.git] / base / applications / clipbrd / clipbrd.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Clipboard Viewer
4 * FILE: base/applications/clipbrd/clipbrd.c
5 * PURPOSE: Provides a view of the contents of the ReactOS clipboard.
6 * PROGRAMMERS: Ricardo Hanke
7 */
8
9 #include "precomp.h"
10
11 static const WCHAR szClassName[] = L"ClipBookWClass";
12
13 CLIPBOARD_GLOBALS Globals;
14 SCROLLSTATE Scrollstate;
15
16 static void UpdateLinesToScroll(void)
17 {
18 UINT uLinesToScroll;
19
20 if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &uLinesToScroll, 0))
21 {
22 Globals.uLinesToScroll = 3;
23 }
24 else
25 {
26 Globals.uLinesToScroll = uLinesToScroll;
27 }
28 }
29
30 static void SaveClipboardToFile(void)
31 {
32 OPENFILENAMEW sfn;
33 WCHAR szFileName[MAX_PATH];
34 WCHAR szFilterMask[MAX_STRING_LEN + 10];
35 LPWSTR c;
36
37 ZeroMemory(&szFilterMask, sizeof(szFilterMask));
38 c = szFilterMask + LoadStringW(Globals.hInstance, STRING_FORMAT_NT, szFilterMask, MAX_STRING_LEN) + 1;
39 wcscpy(c, L"*.clp");
40
41 ZeroMemory(&szFileName, sizeof(szFileName));
42 ZeroMemory(&sfn, sizeof(sfn));
43 sfn.lStructSize = sizeof(sfn);
44 sfn.hwndOwner = Globals.hMainWnd;
45 sfn.hInstance = Globals.hInstance;
46 sfn.lpstrFilter = szFilterMask;
47 sfn.lpstrFile = szFileName;
48 sfn.nMaxFile = ARRAYSIZE(szFileName);
49 sfn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
50 sfn.lpstrDefExt = L"clp";
51
52 if (!GetSaveFileNameW(&sfn))
53 return;
54
55 if (!OpenClipboard(Globals.hMainWnd))
56 {
57 ShowLastWin32Error(Globals.hMainWnd);
58 return;
59 }
60
61 WriteClipboardFile(szFileName, CLIP_FMT_NT /* CLIP_FMT_31 */);
62
63 CloseClipboard();
64 }
65
66 static void LoadClipboardDataFromFile(LPWSTR lpszFileName)
67 {
68 if (MessageBoxRes(Globals.hMainWnd, Globals.hInstance,
69 STRING_DELETE_MSG, STRING_DELETE_TITLE,
70 MB_ICONWARNING | MB_YESNO) != IDYES)
71 {
72 return;
73 }
74
75 if (!OpenClipboard(Globals.hMainWnd))
76 {
77 ShowLastWin32Error(Globals.hMainWnd);
78 return;
79 }
80
81 EmptyClipboard();
82 ReadClipboardFile(lpszFileName);
83
84 CloseClipboard();
85 }
86
87 static void LoadClipboardFromFile(void)
88 {
89 OPENFILENAMEW ofn;
90 WCHAR szFileName[MAX_PATH];
91 WCHAR szFilterMask[MAX_STRING_LEN + 10];
92 LPWSTR c;
93
94 ZeroMemory(&szFilterMask, sizeof(szFilterMask));
95 c = szFilterMask + LoadStringW(Globals.hInstance, STRING_FORMAT_GEN, szFilterMask, MAX_STRING_LEN) + 1;
96 wcscpy(c, L"*.clp");
97
98 ZeroMemory(&szFileName, sizeof(szFileName));
99 ZeroMemory(&ofn, sizeof(ofn));
100 ofn.lStructSize = sizeof(ofn);
101 ofn.hwndOwner = Globals.hMainWnd;
102 ofn.hInstance = Globals.hInstance;
103 ofn.lpstrFilter = szFilterMask;
104 ofn.lpstrFile = szFileName;
105 ofn.nMaxFile = ARRAYSIZE(szFileName);
106 ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
107
108 if (!GetOpenFileNameW(&ofn))
109 return;
110
111 LoadClipboardDataFromFile(szFileName);
112 }
113
114 static void LoadClipboardFromDrop(HDROP hDrop)
115 {
116 WCHAR szFileName[MAX_PATH];
117
118 DragQueryFileW(hDrop, 0, szFileName, ARRAYSIZE(szFileName));
119 DragFinish(hDrop);
120
121 LoadClipboardDataFromFile(szFileName);
122 }
123
124 static void SetDisplayFormat(UINT uFormat)
125 {
126 CheckMenuItem(Globals.hMenu, Globals.uCheckedItem, MF_BYCOMMAND | MF_UNCHECKED);
127 Globals.uCheckedItem = uFormat + CMD_AUTOMATIC;
128 CheckMenuItem(Globals.hMenu, Globals.uCheckedItem, MF_BYCOMMAND | MF_CHECKED);
129
130 if (uFormat == 0)
131 {
132 Globals.uDisplayFormat = GetAutomaticClipboardFormat();
133 }
134 else
135 {
136 Globals.uDisplayFormat = uFormat;
137 }
138
139 if (Globals.hDspBmp)
140 {
141 DeleteObject(Globals.hDspBmp);
142 }
143
144 ZeroMemory(&Scrollstate, sizeof(Scrollstate));
145 UpdateWindowScrollState(Globals.hMainWnd, Globals.hDspBmp, &Scrollstate);
146
147 InvalidateRect(Globals.hMainWnd, NULL, TRUE);
148 }
149
150 static void InitMenuPopup(HMENU hMenu, LPARAM index)
151 {
152 if ((GetMenuItemID(hMenu, 0) == CMD_DELETE) || (GetMenuItemID(hMenu, 1) == CMD_SAVE_AS))
153 {
154 if (CountClipboardFormats() == 0)
155 {
156 EnableMenuItem(hMenu, CMD_DELETE, MF_GRAYED);
157 EnableMenuItem(hMenu, CMD_SAVE_AS, MF_GRAYED);
158 }
159 else
160 {
161 EnableMenuItem(hMenu, CMD_DELETE, MF_ENABLED);
162 EnableMenuItem(hMenu, CMD_SAVE_AS, MF_ENABLED);
163 }
164 }
165
166 DrawMenuBar(Globals.hMainWnd);
167 }
168
169 static void UpdateDisplayMenu(void)
170 {
171 UINT uFormat;
172 WCHAR szFormatName[MAX_FMT_NAME_LEN + 1];
173 HMENU hMenu;
174
175 hMenu = GetSubMenu(Globals.hMenu, DISPLAY_MENU_POS);
176
177 while (GetMenuItemCount(hMenu) > 1)
178 {
179 DeleteMenu(hMenu, 1, MF_BYPOSITION);
180 }
181
182 if (CountClipboardFormats() == 0)
183 return;
184
185 if (!OpenClipboard(Globals.hMainWnd))
186 return;
187
188 AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
189
190 uFormat = EnumClipboardFormats(0);
191 while (uFormat)
192 {
193 RetrieveClipboardFormatName(Globals.hInstance, uFormat, TRUE, szFormatName, ARRAYSIZE(szFormatName));
194
195 if (!IsClipboardFormatSupported(uFormat))
196 {
197 AppendMenuW(hMenu, MF_STRING | MF_GRAYED, 0, szFormatName);
198 }
199 else
200 {
201 AppendMenuW(hMenu, MF_STRING, CMD_AUTOMATIC + uFormat, szFormatName);
202 }
203
204 uFormat = EnumClipboardFormats(uFormat);
205 }
206
207 CloseClipboard();
208 }
209
210 static int ClipboardCommandHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
211 {
212 switch (LOWORD(wParam))
213 {
214 case CMD_OPEN:
215 {
216 LoadClipboardFromFile();
217 break;
218 }
219
220 case CMD_SAVE_AS:
221 {
222 SaveClipboardToFile();
223 break;
224 }
225
226 case CMD_EXIT:
227 {
228 PostMessageW(Globals.hMainWnd, WM_CLOSE, 0, 0);
229 break;
230 }
231
232 case CMD_DELETE:
233 {
234 if (MessageBoxRes(Globals.hMainWnd, Globals.hInstance,
235 STRING_DELETE_MSG, STRING_DELETE_TITLE,
236 MB_ICONWARNING | MB_YESNO) != IDYES)
237 {
238 break;
239 }
240
241 DeleteClipboardContent();
242 break;
243 }
244
245 case CMD_AUTOMATIC:
246 {
247 SetDisplayFormat(0);
248 break;
249 }
250
251 case CMD_HELP:
252 {
253 HtmlHelpW(Globals.hMainWnd, L"clipbrd.chm", 0, 0);
254 break;
255 }
256
257 case CMD_ABOUT:
258 {
259 WCHAR szTitle[MAX_STRING_LEN];
260 HICON hIcon;
261
262 hIcon = LoadIconW(Globals.hInstance, MAKEINTRESOURCE(CLIPBRD_ICON));
263 LoadStringW(Globals.hInstance, STRING_CLIPBOARD, szTitle, ARRAYSIZE(szTitle));
264 ShellAboutW(Globals.hMainWnd, szTitle, 0, hIcon);
265 DeleteObject(hIcon);
266 break;
267 }
268
269 default:
270 {
271 break;
272 }
273 }
274 return 0;
275 }
276
277 static void ClipboardPaintHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
278 {
279 HDC hdc;
280 PAINTSTRUCT ps;
281 RECT rc;
282
283 if (!OpenClipboard(Globals.hMainWnd))
284 return;
285
286 hdc = BeginPaint(hWnd, &ps);
287 GetClientRect(hWnd, &rc);
288
289 switch (Globals.uDisplayFormat)
290 {
291 case CF_NONE:
292 {
293 break;
294 }
295
296 case CF_UNICODETEXT:
297 {
298 DrawTextFromClipboard(hdc, &rc, DT_LEFT | DT_NOPREFIX);
299 break;
300 }
301
302 case CF_BITMAP:
303 {
304 BitBltFromClipboard(hdc, rc.left, rc.top, rc.right, rc.bottom, 0, 0, SRCCOPY);
305 break;
306 }
307
308 case CF_DIB:
309 {
310 SetDIBitsToDeviceFromClipboard(CF_DIB, hdc, rc.left, rc.top, 0, 0, 0, DIB_RGB_COLORS);
311 break;
312 }
313
314 case CF_DIBV5:
315 {
316 SetDIBitsToDeviceFromClipboard(CF_DIBV5, hdc, rc.left, rc.top, 0, 0, 0, DIB_RGB_COLORS);
317 break;
318 }
319
320 case CF_METAFILEPICT:
321 {
322 PlayMetaFileFromClipboard(hdc, &rc);
323 break;
324 }
325
326 case CF_ENHMETAFILE:
327 {
328 PlayEnhMetaFileFromClipboard(hdc, &rc);
329 break;
330 }
331
332 default:
333 {
334 DrawTextFromResource(Globals.hInstance, ERROR_UNSUPPORTED_FORMAT, hdc, &rc, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX);
335 break;
336 }
337 }
338
339 EndPaint(hWnd, &ps);
340
341 CloseClipboard();
342 }
343
344 static LRESULT WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
345 {
346 switch(uMsg)
347 {
348 case WM_CREATE:
349 {
350 Globals.hMenu = GetMenu(hWnd);
351 Globals.hWndNext = SetClipboardViewer(hWnd);
352 UpdateDisplayMenu();
353 SetDisplayFormat(0);
354 break;
355 }
356
357 case WM_CLOSE:
358 {
359 DestroyWindow(hWnd);
360 break;
361 }
362
363 case WM_DESTROY:
364 {
365 ChangeClipboardChain(hWnd, Globals.hWndNext);
366 PostQuitMessage(0);
367 break;
368 }
369
370 case WM_PAINT:
371 {
372 ClipboardPaintHandler(hWnd, uMsg, wParam, lParam);
373 break;
374 }
375
376 case WM_KEYDOWN:
377 {
378 HandleKeyboardScrollEvents(hWnd, uMsg, wParam, lParam);
379 break;
380 }
381
382 case WM_MOUSEWHEEL:
383 {
384 HandleMouseScrollEvents(hWnd, uMsg, wParam, lParam, &Scrollstate);
385 break;
386 }
387
388 case WM_HSCROLL:
389 {
390 HandleHorizontalScrollEvents(hWnd, uMsg, wParam, lParam, &Scrollstate);
391 break;
392 }
393
394 case WM_VSCROLL:
395 {
396 HandleVerticalScrollEvents(hWnd, uMsg, wParam, lParam, &Scrollstate);
397 break;
398 }
399
400 case WM_SIZE:
401 {
402 UpdateWindowScrollState(hWnd, Globals.hDspBmp, &Scrollstate);
403
404 if ((Globals.uDisplayFormat == CF_METAFILEPICT) ||
405 (Globals.uDisplayFormat == CF_ENHMETAFILE) ||
406 (Globals.uDisplayFormat == CF_DSPENHMETAFILE) ||
407 (Globals.uDisplayFormat == CF_DSPMETAFILEPICT))
408 {
409 InvalidateRect(Globals.hMainWnd, NULL, FALSE);
410 }
411 else if (!IsClipboardFormatSupported(Globals.uDisplayFormat))
412 {
413 InvalidateRect(Globals.hMainWnd, NULL, TRUE);
414 }
415
416 break;
417 }
418
419 case WM_CHANGECBCHAIN:
420 {
421 if ((HWND)wParam == Globals.hWndNext)
422 {
423 Globals.hWndNext = (HWND)lParam;
424 }
425 else if (Globals.hWndNext != NULL)
426 {
427 SendMessageW(Globals.hWndNext, uMsg, wParam, lParam);
428 }
429
430 break;
431 }
432
433 case WM_DRAWCLIPBOARD:
434 {
435 UpdateDisplayMenu();
436 SetDisplayFormat(0);
437
438 SendMessageW(Globals.hWndNext, uMsg, wParam, lParam);
439 break;
440 }
441
442 case WM_COMMAND:
443 {
444 if ((LOWORD(wParam) > CMD_AUTOMATIC))
445 {
446 SetDisplayFormat(LOWORD(wParam) - CMD_AUTOMATIC);
447 }
448 else
449 {
450 ClipboardCommandHandler(hWnd, uMsg, wParam, lParam);
451 }
452 break;
453 }
454
455 case WM_INITMENUPOPUP:
456 {
457 InitMenuPopup((HMENU)wParam, lParam);
458 break;
459 }
460
461 case WM_DROPFILES:
462 {
463 LoadClipboardFromDrop((HDROP)wParam);
464 break;
465 }
466
467 case WM_QUERYNEWPALETTE:
468 {
469 if (RealizeClipboardPalette(hWnd) != GDI_ERROR)
470 {
471 InvalidateRect(hWnd, NULL, TRUE);
472 UpdateWindow(hWnd);
473 return TRUE;
474 }
475 return FALSE;
476 }
477
478 case WM_PALETTECHANGED:
479 {
480 if ((HWND)wParam != hWnd)
481 {
482 if (RealizeClipboardPalette(hWnd) != GDI_ERROR)
483 {
484 InvalidateRect(hWnd, NULL, TRUE);
485 UpdateWindow(hWnd);
486 }
487 }
488 break;
489 }
490
491 case WM_SYSCOLORCHANGE:
492 {
493 SetDisplayFormat(Globals.uDisplayFormat);
494 break;
495 }
496
497 case WM_SETTINGCHANGE:
498 {
499 if (wParam == SPI_SETWHEELSCROLLLINES)
500 {
501 UpdateLinesToScroll();
502 }
503 break;
504 }
505
506 default:
507 {
508 return DefWindowProc(hWnd, uMsg, wParam, lParam);
509 }
510 }
511 return 0;
512 }
513
514 int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
515 {
516 MSG msg;
517 HACCEL hAccel;
518 HWND hPrevWindow;
519 WNDCLASSEXW wndclass;
520 WCHAR szBuffer[MAX_STRING_LEN];
521
522 hPrevWindow = FindWindowW(szClassName, NULL);
523 if (hPrevWindow)
524 {
525 BringWindowToFront(hPrevWindow);
526 return 0;
527 }
528
529 ZeroMemory(&Globals, sizeof(Globals));
530 Globals.hInstance = hInstance;
531
532 ZeroMemory(&wndclass, sizeof(wndclass));
533 wndclass.cbSize = sizeof(wndclass);
534 wndclass.lpfnWndProc = MainWndProc;
535 wndclass.hInstance = hInstance;
536 wndclass.hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(CLIPBRD_ICON));
537 wndclass.hCursor = LoadCursorW(0, IDC_ARROW);
538 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
539 wndclass.lpszMenuName = MAKEINTRESOURCEW(MAIN_MENU);
540 wndclass.lpszClassName = szClassName;
541
542 if (!RegisterClassExW(&wndclass))
543 {
544 ShowLastWin32Error(NULL);
545 return 0;
546 }
547
548 LoadStringW(hInstance, STRING_CLIPBOARD, szBuffer, ARRAYSIZE(szBuffer));
549 Globals.hMainWnd = CreateWindowExW(WS_EX_CLIENTEDGE | WS_EX_ACCEPTFILES,
550 szClassName,
551 szBuffer,
552 WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
553 CW_USEDEFAULT,
554 CW_USEDEFAULT,
555 CW_USEDEFAULT,
556 CW_USEDEFAULT,
557 NULL,
558 NULL,
559 Globals.hInstance,
560 NULL);
561 if (!Globals.hMainWnd)
562 {
563 ShowLastWin32Error(NULL);
564 return 0;
565 }
566
567 ShowWindow(Globals.hMainWnd, nCmdShow);
568 UpdateWindow(Globals.hMainWnd);
569
570 hAccel = LoadAcceleratorsW(Globals.hInstance, MAKEINTRESOURCEW(ID_ACCEL));
571 if (!hAccel)
572 {
573 ShowLastWin32Error(Globals.hMainWnd);
574 }
575
576 /* If the user provided a path to a clipboard data file, try to open it */
577 if (lpCmdLine != NULL && *lpCmdLine)
578 LoadClipboardDataFromFile(lpCmdLine);
579
580 UpdateLinesToScroll();
581
582 while (GetMessageW(&msg, 0, 0, 0))
583 {
584 if (!TranslateAcceleratorW(Globals.hMainWnd, hAccel, &msg))
585 {
586 TranslateMessage(&msg);
587 DispatchMessageW(&msg);
588 }
589 }
590
591 if (Globals.hDspBmp)
592 {
593 DeleteObject(Globals.hDspBmp);
594 }
595
596 return (int)msg.wParam;
597 }