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