[OLEDLG]
[reactos.git] / reactos / dll / win32 / oledlg / pastespl.c
1 /*
2 * OleUIPasteSpecial implementation
3 *
4 * Copyright 2006 Huw Davies
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define COBJMACROS
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
28
29 #include <stdarg.h>
30
31 #include <windef.h>
32 #include <winbase.h>
33 //#include "winerror.h"
34 #include <wingdi.h>
35 #include <winuser.h>
36 //#include "winnls.h"
37 //#include "oledlg.h"
38
39 #include "oledlg_private.h"
40 #include "resource.h"
41
42 #include <wine/debug.h>
43 #include <wine/unicode.h>
44
45 WINE_DEFAULT_DEBUG_CHANNEL(ole);
46
47 typedef struct
48 {
49 OLEUIPASTESPECIALW *ps;
50 DWORD flags;
51 WCHAR *source_name;
52 WCHAR *link_source_name;
53 WCHAR *type_name;
54 WCHAR *link_type_name;
55 LPOLESTR app_name;
56 } ps_struct_t;
57
58 static const struct ps_flag
59 {
60 DWORD flag;
61 const char *name;
62 } ps_flags[] = {
63 #define PS_FLAG_ENTRY(p) {p, #p}
64 PS_FLAG_ENTRY(PSF_SHOWHELP),
65 PS_FLAG_ENTRY(PSF_SELECTPASTE),
66 PS_FLAG_ENTRY(PSF_SELECTPASTELINK),
67 PS_FLAG_ENTRY(PSF_CHECKDISPLAYASICON),
68 PS_FLAG_ENTRY(PSF_DISABLEDISPLAYASICON),
69 PS_FLAG_ENTRY(PSF_HIDECHANGEICON),
70 PS_FLAG_ENTRY(PSF_STAYONCLIPBOARDCHANGE),
71 PS_FLAG_ENTRY(PSF_NOREFRESHDATAOBJECT),
72 {-1, NULL}
73 #undef PS_FLAG_ENTRY
74 };
75
76 static void dump_ps_flags(DWORD flags)
77 {
78 char flagstr[1000] = "";
79
80 const struct ps_flag *flag = ps_flags;
81 for( ; flag->name; flag++) {
82 if(flags & flag->flag) {
83 strcat(flagstr, flag->name);
84 strcat(flagstr, "|");
85 }
86 }
87 TRACE("flags %08x %s\n", flags, flagstr);
88 }
89
90 static void dump_pastespecial(const OLEUIPASTESPECIALW *ps)
91 {
92 INT i;
93 UINT j;
94
95 dump_ps_flags(ps->dwFlags);
96 TRACE("hwnd %p caption %s hook %p custdata %lx\n",
97 ps->hWndOwner, debugstr_w(ps->lpszCaption), ps->lpfnHook, ps->lCustData);
98 if(IS_INTRESOURCE(ps->lpszTemplate))
99 TRACE("hinst %p template %04x hresource %p\n", ps->hInstance, (WORD)(ULONG_PTR)ps->lpszTemplate, ps->hResource);
100 else
101 TRACE("hinst %p template %s hresource %p\n", ps->hInstance, debugstr_w(ps->lpszTemplate), ps->hResource);
102 TRACE("dataobj %p arrpasteent %p cpasteent %d arrlinktype %p clinktype %d\n",
103 ps->lpSrcDataObj, ps->arrPasteEntries, ps->cPasteEntries,
104 ps->arrLinkTypes, ps->cLinkTypes);
105 TRACE("cclsidex %d lpclsidex %p nselect %d flink %d hmetapict %p size(%d,%d)\n",
106 ps->cClsidExclude, ps->lpClsidExclude, ps->nSelectedIndex, ps->fLink,
107 ps->hMetaPict, ps->sizel.cx, ps->sizel.cy);
108 for(i = 0; i < ps->cPasteEntries; i++)
109 {
110 TRACE("arrPasteEntries[%d]: cFormat %08x pTargetDevice %p dwAspect %d lindex %d tymed %d\n",
111 i, ps->arrPasteEntries[i].fmtetc.cfFormat, ps->arrPasteEntries[i].fmtetc.ptd,
112 ps->arrPasteEntries[i].fmtetc.dwAspect, ps->arrPasteEntries[i].fmtetc.lindex,
113 ps->arrPasteEntries[i].fmtetc.tymed);
114 TRACE("\tformat name %s result text %s flags %04x\n", debugstr_w(ps->arrPasteEntries[i].lpstrFormatName),
115 debugstr_w(ps->arrPasteEntries[i].lpstrResultText), ps->arrPasteEntries[i].dwFlags);
116 }
117 for(i = 0; i < ps->cLinkTypes; i++)
118 TRACE("arrLinkTypes[%d] %08x\n", i, ps->arrLinkTypes[i]);
119 for(j = 0; j < ps->cClsidExclude; j++)
120 TRACE("lpClsidExclude[%u] %s\n", j, debugstr_guid(&ps->lpClsidExclude[j]));
121
122 }
123
124 static inline WCHAR *strdupAtoW(const char *str)
125 {
126 DWORD len;
127 WCHAR *ret;
128 if(!str) return NULL;
129 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
130 ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
131 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
132 return ret;
133 }
134
135 static inline WCHAR *strdupW(const WCHAR *str)
136 {
137 DWORD len;
138 WCHAR *ret;
139 if(!str) return NULL;
140 len = lstrlenW(str) + 1;
141 ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
142 memcpy(ret, str, len * sizeof(WCHAR));
143 return ret;
144 }
145
146 static void get_descriptors(HWND hdlg, ps_struct_t *ps_struct)
147 {
148 FORMATETC fmtetc;
149 STGMEDIUM stg;
150
151 fmtetc.tymed = TYMED_HGLOBAL;
152 fmtetc.dwAspect = DVASPECT_CONTENT;
153 fmtetc.ptd = NULL;
154 fmtetc.lindex = -1;
155
156 fmtetc.cfFormat = cf_object_descriptor;
157 if(IDataObject_GetData(ps_struct->ps->lpSrcDataObj, &fmtetc, &stg) == S_OK)
158 {
159 OBJECTDESCRIPTOR *obj_desc = GlobalLock(stg.u.hGlobal);
160 if(obj_desc->dwSrcOfCopy)
161 ps_struct->source_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwSrcOfCopy));
162 if(obj_desc->dwFullUserTypeName)
163 ps_struct->type_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwFullUserTypeName));
164 OleRegGetUserType(&obj_desc->clsid, USERCLASSTYPE_APPNAME, &ps_struct->app_name);
165 /* Get the icon here. If dwDrawAspect & DVASCPECT_ICON call GetData(CF_METAFILEPICT), otherwise
166 native calls OleGetIconFromClass(obj_desc->clsid) */
167 GlobalUnlock(stg.u.hGlobal);
168 GlobalFree(stg.u.hGlobal);
169 }
170 else
171 {
172 /* Try to get some data using some of the other clipboard formats */
173 }
174
175 fmtetc.cfFormat = cf_link_src_descriptor;
176 if(IDataObject_GetData(ps_struct->ps->lpSrcDataObj, &fmtetc, &stg) == S_OK)
177 {
178 OBJECTDESCRIPTOR *obj_desc = GlobalLock(stg.u.hGlobal);
179 if(obj_desc->dwSrcOfCopy)
180 ps_struct->link_source_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwSrcOfCopy));
181 if(obj_desc->dwFullUserTypeName)
182 ps_struct->link_type_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwFullUserTypeName));
183 GlobalUnlock(stg.u.hGlobal);
184 GlobalFree(stg.u.hGlobal);
185 }
186
187 if(ps_struct->source_name == NULL && ps_struct->link_source_name == NULL)
188 {
189 WCHAR buf[200];
190 LoadStringW(OLEDLG_hInstance, IDS_PS_UNKNOWN_SRC, buf, sizeof(buf)/sizeof(WCHAR));
191 ps_struct->source_name = strdupW(buf);
192 }
193
194 if(ps_struct->type_name == NULL && ps_struct->link_type_name == NULL)
195 {
196 WCHAR buf[200];
197 LoadStringW(OLEDLG_hInstance, IDS_PS_UNKNOWN_TYPE, buf, sizeof(buf)/sizeof(WCHAR));
198 ps_struct->type_name = strdupW(buf);
199 }
200 }
201
202 static BOOL add_entry_to_lb(HWND hdlg, UINT id, OLEUIPASTEENTRYW *pe)
203 {
204 HWND hwnd = GetDlgItem(hdlg, id);
205 BOOL ret = FALSE;
206
207 /* FIXME %s handling */
208
209 /* Note that this suffers from the same bug as native, in that if a new string
210 is a substring of an already added string, then the FINDSTRING will succeed
211 this is probably not what we want */
212 if(SendMessageW(hwnd, LB_FINDSTRING, 0, (LPARAM)pe->lpstrFormatName) == -1)
213 {
214 LRESULT pos = SendMessageW(hwnd, LB_ADDSTRING, 0, (LPARAM)pe->lpstrFormatName);
215 SendMessageW(hwnd, LB_SETITEMDATA, pos, (LPARAM)pe);
216 ret = TRUE;
217 }
218 return ret;
219 }
220
221 static DWORD init_pastelist(HWND hdlg, OLEUIPASTESPECIALW *ps)
222 {
223 IEnumFORMATETC *penum;
224 HRESULT hr;
225 FORMATETC fmts[20];
226 DWORD fetched, items_added = 0;
227
228 hr = IDataObject_EnumFormatEtc(ps->lpSrcDataObj, DATADIR_GET, &penum);
229 if(FAILED(hr))
230 {
231 WARN("Unable to create IEnumFORMATETC\n");
232 return 0;
233 }
234
235 /* The native version grabs only the first 20 fmts and we do the same */
236 hr = IEnumFORMATETC_Next(penum, sizeof(fmts)/sizeof(fmts[0]), fmts, &fetched);
237 TRACE("got %d formats hr %08x\n", fetched, hr);
238
239 if(SUCCEEDED(hr))
240 {
241 DWORD src_fmt, req_fmt;
242 for(req_fmt = 0; req_fmt < ps->cPasteEntries; req_fmt++)
243 {
244 /* This is used by update_structure() to set nSelectedIndex on exit */
245 ps->arrPasteEntries[req_fmt].dwScratchSpace = req_fmt;
246 TRACE("req_fmt %x\n", ps->arrPasteEntries[req_fmt].fmtetc.cfFormat);
247 for(src_fmt = 0; src_fmt < fetched; src_fmt++)
248 {
249 TRACE("\tenum'ed fmt %x\n", fmts[src_fmt].cfFormat);
250 if(ps->arrPasteEntries[req_fmt].fmtetc.cfFormat == fmts[src_fmt].cfFormat)
251 {
252 add_entry_to_lb(hdlg, IDC_PS_PASTELIST, ps->arrPasteEntries + req_fmt);
253 items_added++;
254 break;
255 }
256 }
257 }
258 }
259
260 IEnumFORMATETC_Release(penum);
261 EnableWindow(GetDlgItem(hdlg, IDC_PS_PASTE), items_added != 0);
262 return items_added;
263 }
264
265 static DWORD init_linklist(HWND hdlg, OLEUIPASTESPECIALW *ps)
266 {
267 HRESULT hr;
268 DWORD supported_mask = 0;
269 DWORD items_added = 0;
270 int link, req_fmt;
271 FORMATETC fmt = {0, NULL, DVASPECT_CONTENT, -1, -1};
272
273 for(link = 0; link < ps->cLinkTypes && link < PS_MAXLINKTYPES; link++)
274 {
275 fmt.cfFormat = ps->arrLinkTypes[link];
276 hr = IDataObject_QueryGetData(ps->lpSrcDataObj, &fmt);
277 if(hr == S_OK)
278 supported_mask |= 1 << link;
279 }
280 TRACE("supported_mask %02x\n", supported_mask);
281 for(req_fmt = 0; req_fmt < ps->cPasteEntries; req_fmt++)
282 {
283 DWORD linktypes;
284 if(ps->arrPasteEntries[req_fmt].dwFlags & OLEUIPASTE_LINKANYTYPE)
285 linktypes = 0xff;
286 else
287 linktypes = ps->arrPasteEntries[req_fmt].dwFlags & 0xff;
288
289 if(linktypes & supported_mask)
290 {
291 add_entry_to_lb(hdlg, IDC_PS_PASTELINKLIST, ps->arrPasteEntries + req_fmt);
292 items_added++;
293 }
294 }
295
296 EnableWindow(GetDlgItem(hdlg, IDC_PS_PASTELINK), items_added != 0);
297 return items_added;
298 }
299
300 /* copies src_list_id into the display list */
301 static void update_display_list(HWND hdlg, UINT src_list_id)
302 {
303 LONG count, i, old_pos;
304 WCHAR txt[256];
305 LONG item_data;
306 HWND display_list = GetDlgItem(hdlg, IDC_PS_DISPLAYLIST);
307 HWND list = GetDlgItem(hdlg, src_list_id);
308
309 old_pos = SendMessageW(display_list, LB_GETCURSEL, 0, 0);
310 if(old_pos == -1) old_pos = 0;
311
312 SendMessageW(display_list, WM_SETREDRAW, 0, 0);
313 SendMessageW(display_list, LB_RESETCONTENT, 0, 0);
314 count = SendMessageW(list, LB_GETCOUNT, 0, 0);
315 for(i = 0; i < count; i++)
316 {
317 SendMessageW(list, LB_GETTEXT, i, (LPARAM)txt);
318 item_data = SendMessageW(list, LB_GETITEMDATA, i, 0);
319 SendMessageW(display_list, LB_INSERTSTRING, i, (LPARAM)txt);
320 SendMessageW(display_list, LB_SETITEMDATA, i, item_data);
321 }
322 SendMessageW(display_list, LB_SETCURSEL, 0, 0);
323 SendMessageW(display_list, WM_SETREDRAW, 1, 0);
324 if(GetForegroundWindow() == hdlg)
325 SetFocus(display_list);
326 }
327
328 static void init_lists(HWND hdlg, ps_struct_t *ps_struct)
329 {
330 DWORD pastes_added = init_pastelist(hdlg, ps_struct->ps);
331 DWORD links_added = init_linklist(hdlg, ps_struct->ps);
332 UINT check_id, list_id;
333
334 if((ps_struct->flags & (PSF_SELECTPASTE | PSF_SELECTPASTELINK)) == 0)
335 ps_struct->flags |= PSF_SELECTPASTE;
336
337 if(!pastes_added && !links_added)
338 ps_struct->flags &= ~(PSF_SELECTPASTE | PSF_SELECTPASTELINK);
339 else if(!pastes_added && (ps_struct->flags & PSF_SELECTPASTE))
340 {
341 ps_struct->flags &= ~PSF_SELECTPASTE;
342 ps_struct->flags |= PSF_SELECTPASTELINK;
343 }
344 else if(!links_added && (ps_struct->flags & PSF_SELECTPASTELINK))
345 {
346 ps_struct->flags &= ~PSF_SELECTPASTELINK;
347 ps_struct->flags |= PSF_SELECTPASTE;
348 }
349
350 check_id = 0;
351 list_id = 0;
352 if(ps_struct->flags & PSF_SELECTPASTE)
353 {
354 check_id = IDC_PS_PASTE;
355 list_id = IDC_PS_PASTELIST;
356 }
357 else if(ps_struct->flags & PSF_SELECTPASTELINK)
358 {
359 check_id = IDC_PS_PASTELINK;
360 list_id = IDC_PS_PASTELINKLIST;
361 }
362
363 CheckRadioButton(hdlg, IDC_PS_PASTE, IDC_PS_PASTELINK, check_id);
364
365 if(list_id)
366 update_display_list(hdlg, list_id);
367 else
368 EnableWindow(GetDlgItem(hdlg, IDOK), 0);
369 }
370
371 static void update_src_text(HWND hdlg, const ps_struct_t *ps_struct)
372 {
373 WCHAR *str;
374
375 if(ps_struct->flags & PSF_SELECTPASTE)
376 {
377 if(ps_struct->source_name)
378 str = ps_struct->source_name;
379 else
380 str = ps_struct->link_source_name;
381
382 }
383 else
384 {
385 if(ps_struct->link_source_name)
386 str = ps_struct->link_source_name;
387 else
388 str = ps_struct->source_name;
389
390 }
391 SetDlgItemTextW(hdlg, IDC_PS_SOURCETEXT, str);
392 }
393
394 static void update_as_icon(HWND hdlg, ps_struct_t *ps_struct)
395 {
396 HWND icon_display = GetDlgItem(hdlg, IDC_PS_ICONDISPLAY);
397 HWND display_as_icon = GetDlgItem(hdlg, IDC_PS_DISPLAYASICON);
398 HWND change_icon = GetDlgItem(hdlg, IDC_PS_CHANGEICON);
399
400 /* FIXME. No as icon handling */
401 ps_struct->flags &= ~PSF_CHECKDISPLAYASICON;
402
403 CheckDlgButton(hdlg, IDC_PS_DISPLAYASICON, ps_struct->flags & PSF_CHECKDISPLAYASICON);
404 EnableWindow(display_as_icon, 0);
405 ShowWindow(icon_display, SW_HIDE);
406 EnableWindow(icon_display, 0);
407 ShowWindow(change_icon, SW_HIDE);
408 EnableWindow(change_icon, 0);
409 }
410
411 static void update_result_text(HWND hdlg, const ps_struct_t *ps_struct)
412 {
413 WCHAR resource_txt[200];
414 UINT res_id;
415 OLEUIPASTEENTRYW *pent;
416 LONG cur_sel;
417 static const WCHAR percent_s[] = {'%','s',0};
418 WCHAR *result_txt, *ptr;
419
420 cur_sel = SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETCURSEL, 0, 0);
421 if(cur_sel == -1) return;
422 pent = (OLEUIPASTEENTRYW*)SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETITEMDATA, cur_sel, 0);
423
424 if(ps_struct->flags & PSF_SELECTPASTE)
425 {
426 if(ps_struct->flags & PSF_CHECKDISPLAYASICON)
427 res_id = IDS_PS_PASTE_OBJECT_AS_ICON;
428 else
429 res_id = IDS_PS_PASTE_DATA;
430 }
431 else
432 {
433 if(ps_struct->flags & PSF_CHECKDISPLAYASICON)
434 res_id = IDS_PS_PASTE_LINK_OBJECT_AS_ICON;
435 else
436 res_id = IDS_PS_PASTE_LINK_DATA;
437 }
438
439 LoadStringW(OLEDLG_hInstance, res_id, resource_txt, sizeof(resource_txt)/sizeof(WCHAR));
440 if((ptr = strstrW(resource_txt, percent_s)))
441 {
442 /* FIXME handle %s in ResultText. Sub appname if IDS_PS_PASTE_OBJECT{_AS_ICON}. Else sub appropriate type name */
443 size_t result_txt_len = strlenW(pent->lpstrResultText);
444 ptrdiff_t offs = (char*)ptr - (char*)resource_txt;
445 result_txt = HeapAlloc(GetProcessHeap(), 0, (strlenW(resource_txt) + result_txt_len - 1) * sizeof(WCHAR));
446 memcpy(result_txt, resource_txt, offs);
447 memcpy((char*)result_txt + offs, pent->lpstrResultText, result_txt_len * sizeof(WCHAR));
448 memcpy((char*)result_txt + offs + result_txt_len * sizeof(WCHAR), ptr + 2, (strlenW(ptr + 2) + 1) * sizeof(WCHAR));
449 }
450 else
451 result_txt = resource_txt;
452
453 SetDlgItemTextW(hdlg, IDC_PS_RESULTTEXT, result_txt);
454
455 if(result_txt != resource_txt)
456 HeapFree(GetProcessHeap(), 0, result_txt);
457
458 }
459
460 static void selection_change(HWND hdlg, ps_struct_t *ps_struct)
461 {
462 update_as_icon(hdlg, ps_struct);
463 update_result_text(hdlg, ps_struct);
464 }
465
466 static void mode_change(HWND hdlg, ps_struct_t *ps_struct, UINT id)
467 {
468 if(id == IDC_PS_PASTE)
469 {
470 ps_struct->flags &= ~PSF_SELECTPASTELINK;
471 ps_struct->flags |= PSF_SELECTPASTE;
472 }
473 else
474 {
475 ps_struct->flags &= ~PSF_SELECTPASTE;
476 ps_struct->flags |= PSF_SELECTPASTELINK;
477 }
478
479 update_src_text(hdlg, ps_struct);
480 update_display_list(hdlg, id == IDC_PS_PASTE ? IDC_PS_PASTELIST : IDC_PS_PASTELINKLIST);
481 selection_change(hdlg, ps_struct);
482 }
483
484 static void post_help_msg(HWND hdlg, ps_struct_t *ps_struct)
485 {
486 PostMessageW(ps_struct->ps->hWndOwner, oleui_msg_help, (WPARAM)hdlg, IDD_PASTESPECIAL);
487 }
488
489 static void send_end_dialog_msg(HWND hdlg, ps_struct_t *ps_struct, UINT id)
490 {
491 SendMessageW(hdlg, oleui_msg_enddialog, id, 0);
492 }
493
494 static void update_structure(HWND hdlg, ps_struct_t *ps_struct)
495 {
496 LONG cur_sel = SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETCURSEL, 0, 0);
497 if(cur_sel != -1)
498 {
499 OLEUIPASTEENTRYW *pent;
500 pent = (OLEUIPASTEENTRYW *)SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETITEMDATA, cur_sel, 0);
501 ps_struct->ps->nSelectedIndex = pent->dwScratchSpace;
502 }
503 ps_struct->ps->dwFlags = ps_struct->flags;
504 ps_struct->ps->fLink = (ps_struct->flags & PSF_SELECTPASTELINK) != 0;
505 }
506
507 static void free_structure(ps_struct_t *ps_struct)
508 {
509 HeapFree(GetProcessHeap(), 0, ps_struct->type_name);
510 HeapFree(GetProcessHeap(), 0, ps_struct->source_name);
511 HeapFree(GetProcessHeap(), 0, ps_struct->link_type_name);
512 HeapFree(GetProcessHeap(), 0, ps_struct->link_source_name);
513 CoTaskMemFree(ps_struct->app_name);
514 HeapFree(GetProcessHeap(), 0, ps_struct);
515 }
516
517 static INT_PTR CALLBACK ps_dlg_proc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp)
518 {
519 /* native uses prop name "Structure", but we're not compatible
520 with that so we'll prepend "Wine_". */
521 static const WCHAR prop_name[] = {'W','i','n','e','_','S','t','r','u','c','t','u','r','e',0};
522 ps_struct_t *ps_struct;
523
524 TRACE("(%p, %04x, %08lx, %08lx)\n", hdlg, msg, wp, lp);
525
526 ps_struct = GetPropW(hdlg, prop_name);
527
528 if(msg != WM_INITDIALOG)
529 {
530 if(!ps_struct)
531 return 0;
532
533 if(ps_struct->ps->lpfnHook)
534 {
535 INT_PTR ret = ps_struct->ps->lpfnHook(hdlg, msg, wp, lp);
536 if(ret) return ret;
537 }
538 }
539
540 switch(msg)
541 {
542 case WM_INITDIALOG:
543 {
544 ps_struct = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps_struct));
545 ps_struct->ps = (OLEUIPASTESPECIALW*)lp;
546 ps_struct->type_name = NULL;
547 ps_struct->source_name = NULL;
548 ps_struct->link_type_name = NULL;
549 ps_struct->link_source_name = NULL;
550 ps_struct->app_name = NULL;
551 ps_struct->flags = ps_struct->ps->dwFlags;
552
553 SetPropW(hdlg, prop_name, ps_struct);
554
555 if(!(ps_struct->ps->dwFlags & PSF_SHOWHELP))
556 {
557 ShowWindow(GetDlgItem(hdlg, IDC_OLEUIHELP), SW_HIDE);
558 EnableWindow(GetDlgItem(hdlg, IDC_OLEUIHELP), 0);
559 }
560
561 if(ps_struct->ps->lpszCaption)
562 SetWindowTextW(hdlg, ps_struct->ps->lpszCaption);
563
564 get_descriptors(hdlg, ps_struct);
565
566 init_lists(hdlg, ps_struct);
567
568 update_src_text(hdlg, ps_struct);
569
570 selection_change(hdlg, ps_struct);
571
572 SetFocus(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST));
573
574 if(ps_struct->ps->lpfnHook)
575 ps_struct->ps->lpfnHook(hdlg, msg, 0, 0);
576 return FALSE; /* use new focus */
577 }
578 case WM_COMMAND:
579 switch(LOWORD(wp))
580 {
581 case IDC_PS_DISPLAYLIST:
582 switch(HIWORD(wp))
583 {
584 case LBN_SELCHANGE:
585 selection_change(hdlg, ps_struct);
586 return FALSE;
587 default:
588 return FALSE;
589 }
590 case IDC_PS_PASTE:
591 case IDC_PS_PASTELINK:
592 switch(HIWORD(wp))
593 {
594 case BN_CLICKED:
595 mode_change(hdlg, ps_struct, LOWORD(wp));
596 return FALSE;
597
598 default:
599 return FALSE;
600 }
601 case IDC_OLEUIHELP:
602 switch(HIWORD(wp))
603 {
604 case BN_CLICKED:
605 post_help_msg(hdlg, ps_struct);
606 return FALSE;
607 default:
608 return FALSE;
609 }
610 case IDOK:
611 case IDCANCEL:
612 switch(HIWORD(wp))
613 {
614 case BN_CLICKED:
615 send_end_dialog_msg(hdlg, ps_struct, LOWORD(wp));
616 return FALSE;
617 default:
618 return FALSE;
619 }
620 }
621 return FALSE;
622 default:
623 if(msg == oleui_msg_enddialog)
624 {
625 if(wp == IDOK)
626 update_structure(hdlg, ps_struct);
627 EndDialog(hdlg, wp);
628 /* native does its cleanup in WM_DESTROY */
629 RemovePropW(hdlg, prop_name);
630 free_structure(ps_struct);
631 return TRUE;
632 }
633 return FALSE;
634 }
635
636 }
637
638 /***********************************************************************
639 * OleUIPasteSpecialA (OLEDLG.4)
640 */
641 UINT WINAPI OleUIPasteSpecialA(LPOLEUIPASTESPECIALA psA)
642 {
643 OLEUIPASTESPECIALW ps;
644 UINT ret;
645 TRACE("(%p)\n", psA);
646
647 memcpy(&ps, psA, psA->cbStruct);
648
649 ps.lpszCaption = strdupAtoW(psA->lpszCaption);
650 if(!IS_INTRESOURCE(ps.lpszTemplate))
651 ps.lpszTemplate = strdupAtoW(psA->lpszTemplate);
652
653 if(psA->cPasteEntries > 0)
654 {
655 DWORD size = psA->cPasteEntries * sizeof(ps.arrPasteEntries[0]);
656 INT i;
657
658 ps.arrPasteEntries = HeapAlloc(GetProcessHeap(), 0, size);
659 memcpy(ps.arrPasteEntries, psA->arrPasteEntries, size);
660 for(i = 0; i < psA->cPasteEntries; i++)
661 {
662 ps.arrPasteEntries[i].lpstrFormatName =
663 strdupAtoW(psA->arrPasteEntries[i].lpstrFormatName);
664 ps.arrPasteEntries[i].lpstrResultText =
665 strdupAtoW(psA->arrPasteEntries[i].lpstrResultText);
666 }
667 }
668
669 ret = OleUIPasteSpecialW(&ps);
670
671 if(psA->cPasteEntries > 0)
672 {
673 INT i;
674 for(i = 0; i < psA->cPasteEntries; i++)
675 {
676 HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.arrPasteEntries[i].lpstrFormatName);
677 HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.arrPasteEntries[i].lpstrResultText);
678 }
679 HeapFree(GetProcessHeap(), 0, ps.arrPasteEntries);
680 }
681 if(!IS_INTRESOURCE(ps.lpszTemplate))
682 HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.lpszTemplate);
683 HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.lpszCaption);
684
685 /* Copy back the output fields */
686 psA->dwFlags = ps.dwFlags;
687 psA->lpSrcDataObj = ps.lpSrcDataObj;
688 psA->nSelectedIndex = ps.nSelectedIndex;
689 psA->fLink = ps.fLink;
690 psA->hMetaPict = ps.hMetaPict;
691 psA->sizel = ps.sizel;
692
693 return ret;
694 }
695
696 /***********************************************************************
697 * OleUIPasteSpecialW (OLEDLG.22)
698 */
699 UINT WINAPI OleUIPasteSpecialW(LPOLEUIPASTESPECIALW ps)
700 {
701 LPCDLGTEMPLATEW dlg_templ = (LPCDLGTEMPLATEW)ps->hResource;
702 UINT ret;
703
704 TRACE("(%p)\n", ps);
705
706 if(TRACE_ON(ole)) dump_pastespecial(ps);
707
708 if(!ps->lpSrcDataObj)
709 OleGetClipboard(&ps->lpSrcDataObj);
710
711 if(ps->hInstance || !ps->hResource)
712 {
713 HINSTANCE hInst = ps->hInstance ? ps->hInstance : OLEDLG_hInstance;
714 const WCHAR *name = ps->hInstance ? ps->lpszTemplate : MAKEINTRESOURCEW(IDD_PASTESPECIAL4);
715 HRSRC hrsrc;
716
717 if(name == NULL) return OLEUI_ERR_LPSZTEMPLATEINVALID;
718 hrsrc = FindResourceW(hInst, name, MAKEINTRESOURCEW(RT_DIALOG));
719 if(!hrsrc) return OLEUI_ERR_FINDTEMPLATEFAILURE;
720 dlg_templ = LoadResource(hInst, hrsrc);
721 if(!dlg_templ) return OLEUI_ERR_LOADTEMPLATEFAILURE;
722 }
723
724 ret = DialogBoxIndirectParamW(OLEDLG_hInstance, dlg_templ, ps->hWndOwner, ps_dlg_proc, (LPARAM)ps);
725
726 return ret;
727 }