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