cmd: DIR command outputs free space for the path.
[wine.git] / dlls / oledlg / pastespl.c
blob7813ecd0c5f8fd2731be2544fc95f70e68c75e0d
1 /*
2 * OleUIPasteSpecial implementation
4 * Copyright 2006 Huw Davies
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.
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.
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
21 #define COBJMACROS
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "oledlg.h"
33 #include "oledlg_private.h"
34 #include "resource.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40 typedef struct
42 OLEUIPASTESPECIALW *ps;
43 DWORD flags;
44 WCHAR *source_name;
45 WCHAR *link_source_name;
46 WCHAR *type_name;
47 WCHAR *link_type_name;
48 LPOLESTR app_name;
49 } ps_struct_t;
51 static const struct ps_flag
53 DWORD flag;
54 const char *name;
55 } ps_flags[] = {
56 #define PS_FLAG_ENTRY(p) {p, #p}
57 PS_FLAG_ENTRY(PSF_SHOWHELP),
58 PS_FLAG_ENTRY(PSF_SELECTPASTE),
59 PS_FLAG_ENTRY(PSF_SELECTPASTELINK),
60 PS_FLAG_ENTRY(PSF_CHECKDISPLAYASICON),
61 PS_FLAG_ENTRY(PSF_DISABLEDISPLAYASICON),
62 PS_FLAG_ENTRY(PSF_HIDECHANGEICON),
63 PS_FLAG_ENTRY(PSF_STAYONCLIPBOARDCHANGE),
64 PS_FLAG_ENTRY(PSF_NOREFRESHDATAOBJECT),
65 {-1, NULL}
66 #undef PS_FLAG_ENTRY
69 static void dump_ps_flags(DWORD flags)
71 char flagstr[1000] = "";
73 const struct ps_flag *flag = ps_flags;
74 for( ; flag->name; flag++) {
75 if(flags & flag->flag) {
76 strcat(flagstr, flag->name);
77 strcat(flagstr, "|");
80 TRACE("flags %08lx %s\n", flags, flagstr);
83 static void dump_pastespecial(const OLEUIPASTESPECIALW *ps)
85 INT i;
86 UINT j;
88 dump_ps_flags(ps->dwFlags);
89 TRACE("hwnd %p caption %s hook %p custdata %Ix\n",
90 ps->hWndOwner, debugstr_w(ps->lpszCaption), ps->lpfnHook, ps->lCustData);
91 if(IS_INTRESOURCE(ps->lpszTemplate))
92 TRACE("hinst %p template %04x hresource %p\n", ps->hInstance, (WORD)(ULONG_PTR)ps->lpszTemplate, ps->hResource);
93 else
94 TRACE("hinst %p template %s hresource %p\n", ps->hInstance, debugstr_w(ps->lpszTemplate), ps->hResource);
95 TRACE("dataobj %p arrpasteent %p cpasteent %d arrlinktype %p clinktype %d\n",
96 ps->lpSrcDataObj, ps->arrPasteEntries, ps->cPasteEntries,
97 ps->arrLinkTypes, ps->cLinkTypes);
98 TRACE("cclsidex %d lpclsidex %p nselect %d flink %d hmetapict %p size(%ld,%ld)\n",
99 ps->cClsidExclude, ps->lpClsidExclude, ps->nSelectedIndex, ps->fLink,
100 ps->hMetaPict, ps->sizel.cx, ps->sizel.cy);
101 for(i = 0; i < ps->cPasteEntries; i++)
103 TRACE("arrPasteEntries[%d]: cFormat %08x pTargetDevice %p dwAspect %ld lindex %ld tymed %ld\n",
104 i, ps->arrPasteEntries[i].fmtetc.cfFormat, ps->arrPasteEntries[i].fmtetc.ptd,
105 ps->arrPasteEntries[i].fmtetc.dwAspect, ps->arrPasteEntries[i].fmtetc.lindex,
106 ps->arrPasteEntries[i].fmtetc.tymed);
107 TRACE("\tformat name %s result text %s flags %04lx\n", debugstr_w(ps->arrPasteEntries[i].lpstrFormatName),
108 debugstr_w(ps->arrPasteEntries[i].lpstrResultText), ps->arrPasteEntries[i].dwFlags);
110 for(i = 0; i < ps->cLinkTypes; i++)
111 TRACE("arrLinkTypes[%d] %08x\n", i, ps->arrLinkTypes[i]);
112 for(j = 0; j < ps->cClsidExclude; j++)
113 TRACE("lpClsidExclude[%u] %s\n", j, debugstr_guid(&ps->lpClsidExclude[j]));
117 static inline WCHAR *strdupAtoW(const char *str)
119 DWORD len;
120 WCHAR *ret;
121 if(!str) return NULL;
122 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
123 ret = malloc(len * sizeof(WCHAR));
124 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
125 return ret;
128 static void get_descriptors(HWND hdlg, ps_struct_t *ps_struct)
130 FORMATETC fmtetc;
131 STGMEDIUM stg;
133 fmtetc.tymed = TYMED_HGLOBAL;
134 fmtetc.dwAspect = DVASPECT_CONTENT;
135 fmtetc.ptd = NULL;
136 fmtetc.lindex = -1;
138 fmtetc.cfFormat = cf_object_descriptor;
139 if(IDataObject_GetData(ps_struct->ps->lpSrcDataObj, &fmtetc, &stg) == S_OK)
141 OBJECTDESCRIPTOR *obj_desc = GlobalLock(stg.hGlobal);
142 if(obj_desc->dwSrcOfCopy)
143 ps_struct->source_name = wcsdup((WCHAR*)((char*)obj_desc + obj_desc->dwSrcOfCopy));
144 if(obj_desc->dwFullUserTypeName)
145 ps_struct->type_name = wcsdup((WCHAR*)((char*)obj_desc + obj_desc->dwFullUserTypeName));
146 OleRegGetUserType(&obj_desc->clsid, USERCLASSTYPE_APPNAME, &ps_struct->app_name);
147 /* Get the icon here. If dwDrawAspect & DVASCPECT_ICON call GetData(CF_METAFILEPICT), otherwise
148 native calls OleGetIconFromClass(obj_desc->clsid) */
149 GlobalUnlock(stg.hGlobal);
150 GlobalFree(stg.hGlobal);
152 else
154 /* Try to get some data using some of the other clipboard formats */
157 fmtetc.cfFormat = cf_link_src_descriptor;
158 if(IDataObject_GetData(ps_struct->ps->lpSrcDataObj, &fmtetc, &stg) == S_OK)
160 OBJECTDESCRIPTOR *obj_desc = GlobalLock(stg.hGlobal);
161 if(obj_desc->dwSrcOfCopy)
162 ps_struct->link_source_name = wcsdup((WCHAR*)((char*)obj_desc + obj_desc->dwSrcOfCopy));
163 if(obj_desc->dwFullUserTypeName)
164 ps_struct->link_type_name = wcsdup((WCHAR*)((char*)obj_desc + obj_desc->dwFullUserTypeName));
165 GlobalUnlock(stg.hGlobal);
166 GlobalFree(stg.hGlobal);
169 if(ps_struct->source_name == NULL && ps_struct->link_source_name == NULL)
171 WCHAR buf[200];
172 LoadStringW(OLEDLG_hInstance, IDS_PS_UNKNOWN_SRC, buf, ARRAY_SIZE(buf));
173 ps_struct->source_name = wcsdup(buf);
176 if(ps_struct->type_name == NULL && ps_struct->link_type_name == NULL)
178 WCHAR buf[200];
179 LoadStringW(OLEDLG_hInstance, IDS_PS_UNKNOWN_TYPE, buf, ARRAY_SIZE(buf));
180 ps_struct->type_name = wcsdup(buf);
184 static BOOL add_entry_to_lb(HWND hdlg, UINT id, OLEUIPASTEENTRYW *pe)
186 HWND hwnd = GetDlgItem(hdlg, id);
187 BOOL ret = FALSE;
189 /* FIXME %s handling */
191 /* Note that this suffers from the same bug as native, in that if a new string
192 is a substring of an already added string, then the FINDSTRING will succeed
193 this is probably not what we want */
194 if(SendMessageW(hwnd, LB_FINDSTRING, 0, (LPARAM)pe->lpstrFormatName) == -1)
196 LRESULT pos = SendMessageW(hwnd, LB_ADDSTRING, 0, (LPARAM)pe->lpstrFormatName);
197 SendMessageW(hwnd, LB_SETITEMDATA, pos, (LPARAM)pe);
198 ret = TRUE;
200 return ret;
203 static DWORD init_pastelist(HWND hdlg, OLEUIPASTESPECIALW *ps)
205 IEnumFORMATETC *penum;
206 HRESULT hr;
207 FORMATETC fmts[20];
208 DWORD fetched, items_added = 0;
210 hr = IDataObject_EnumFormatEtc(ps->lpSrcDataObj, DATADIR_GET, &penum);
211 if(FAILED(hr))
213 WARN("Unable to create IEnumFORMATETC\n");
214 return 0;
217 /* The native version grabs only the first 20 fmts and we do the same */
218 hr = IEnumFORMATETC_Next(penum, ARRAY_SIZE(fmts), fmts, &fetched);
219 TRACE("got %ld formats hr %08lx\n", fetched, hr);
221 if(SUCCEEDED(hr))
223 DWORD src_fmt, req_fmt;
224 for(req_fmt = 0; req_fmt < ps->cPasteEntries; req_fmt++)
226 /* This is used by update_structure() to set nSelectedIndex on exit */
227 ps->arrPasteEntries[req_fmt].dwScratchSpace = req_fmt;
228 TRACE("req_fmt %x\n", ps->arrPasteEntries[req_fmt].fmtetc.cfFormat);
229 for(src_fmt = 0; src_fmt < fetched; src_fmt++)
231 TRACE("\tenum'ed fmt %x\n", fmts[src_fmt].cfFormat);
232 if(ps->arrPasteEntries[req_fmt].fmtetc.cfFormat == fmts[src_fmt].cfFormat)
234 add_entry_to_lb(hdlg, IDC_PS_PASTELIST, ps->arrPasteEntries + req_fmt);
235 items_added++;
236 break;
242 IEnumFORMATETC_Release(penum);
243 EnableWindow(GetDlgItem(hdlg, IDC_PS_PASTE), items_added != 0);
244 return items_added;
247 static DWORD init_linklist(HWND hdlg, OLEUIPASTESPECIALW *ps)
249 HRESULT hr;
250 DWORD supported_mask = 0;
251 DWORD items_added = 0;
252 int link, req_fmt;
253 FORMATETC fmt = {0, NULL, DVASPECT_CONTENT, -1, -1};
255 for(link = 0; link < ps->cLinkTypes && link < PS_MAXLINKTYPES; link++)
257 fmt.cfFormat = ps->arrLinkTypes[link];
258 hr = IDataObject_QueryGetData(ps->lpSrcDataObj, &fmt);
259 if(hr == S_OK)
260 supported_mask |= 1 << link;
262 TRACE("supported_mask %02lx\n", supported_mask);
263 for(req_fmt = 0; req_fmt < ps->cPasteEntries; req_fmt++)
265 DWORD linktypes;
266 if(ps->arrPasteEntries[req_fmt].dwFlags & OLEUIPASTE_LINKANYTYPE)
267 linktypes = 0xff;
268 else
269 linktypes = ps->arrPasteEntries[req_fmt].dwFlags & 0xff;
271 if(linktypes & supported_mask)
273 add_entry_to_lb(hdlg, IDC_PS_PASTELINKLIST, ps->arrPasteEntries + req_fmt);
274 items_added++;
278 EnableWindow(GetDlgItem(hdlg, IDC_PS_PASTELINK), items_added != 0);
279 return items_added;
282 /* copies src_list_id into the display list */
283 static void update_display_list(HWND hdlg, UINT src_list_id)
285 LONG count, i, old_pos;
286 WCHAR txt[256];
287 LONG item_data;
288 HWND display_list = GetDlgItem(hdlg, IDC_PS_DISPLAYLIST);
289 HWND list = GetDlgItem(hdlg, src_list_id);
291 old_pos = SendMessageW(display_list, LB_GETCURSEL, 0, 0);
292 if(old_pos == -1) old_pos = 0;
294 SendMessageW(display_list, WM_SETREDRAW, 0, 0);
295 SendMessageW(display_list, LB_RESETCONTENT, 0, 0);
296 count = SendMessageW(list, LB_GETCOUNT, 0, 0);
297 for(i = 0; i < count; i++)
299 SendMessageW(list, LB_GETTEXT, i, (LPARAM)txt);
300 item_data = SendMessageW(list, LB_GETITEMDATA, i, 0);
301 SendMessageW(display_list, LB_INSERTSTRING, i, (LPARAM)txt);
302 SendMessageW(display_list, LB_SETITEMDATA, i, item_data);
304 SendMessageW(display_list, LB_SETCURSEL, 0, 0);
305 SendMessageW(display_list, WM_SETREDRAW, 1, 0);
306 if(GetForegroundWindow() == hdlg)
307 SetFocus(display_list);
310 static void init_lists(HWND hdlg, ps_struct_t *ps_struct)
312 DWORD pastes_added = init_pastelist(hdlg, ps_struct->ps);
313 DWORD links_added = init_linklist(hdlg, ps_struct->ps);
314 UINT check_id, list_id;
316 if((ps_struct->flags & (PSF_SELECTPASTE | PSF_SELECTPASTELINK)) == 0)
317 ps_struct->flags |= PSF_SELECTPASTE;
319 if(!pastes_added && !links_added)
320 ps_struct->flags &= ~(PSF_SELECTPASTE | PSF_SELECTPASTELINK);
321 else if(!pastes_added && (ps_struct->flags & PSF_SELECTPASTE))
323 ps_struct->flags &= ~PSF_SELECTPASTE;
324 ps_struct->flags |= PSF_SELECTPASTELINK;
326 else if(!links_added && (ps_struct->flags & PSF_SELECTPASTELINK))
328 ps_struct->flags &= ~PSF_SELECTPASTELINK;
329 ps_struct->flags |= PSF_SELECTPASTE;
332 check_id = 0;
333 list_id = 0;
334 if(ps_struct->flags & PSF_SELECTPASTE)
336 check_id = IDC_PS_PASTE;
337 list_id = IDC_PS_PASTELIST;
339 else if(ps_struct->flags & PSF_SELECTPASTELINK)
341 check_id = IDC_PS_PASTELINK;
342 list_id = IDC_PS_PASTELINKLIST;
345 CheckRadioButton(hdlg, IDC_PS_PASTE, IDC_PS_PASTELINK, check_id);
347 if(list_id)
348 update_display_list(hdlg, list_id);
349 else
350 EnableWindow(GetDlgItem(hdlg, IDOK), 0);
353 static void update_src_text(HWND hdlg, const ps_struct_t *ps_struct)
355 WCHAR *str;
357 if(ps_struct->flags & PSF_SELECTPASTE)
359 if(ps_struct->source_name)
360 str = ps_struct->source_name;
361 else
362 str = ps_struct->link_source_name;
365 else
367 if(ps_struct->link_source_name)
368 str = ps_struct->link_source_name;
369 else
370 str = ps_struct->source_name;
373 SetDlgItemTextW(hdlg, IDC_PS_SOURCETEXT, str);
376 static void update_as_icon(HWND hdlg, ps_struct_t *ps_struct)
378 HWND icon_display = GetDlgItem(hdlg, IDC_PS_ICONDISPLAY);
379 HWND display_as_icon = GetDlgItem(hdlg, IDC_PS_DISPLAYASICON);
380 HWND change_icon = GetDlgItem(hdlg, IDC_PS_CHANGEICON);
382 /* FIXME. No as icon handling */
383 ps_struct->flags &= ~PSF_CHECKDISPLAYASICON;
385 CheckDlgButton(hdlg, IDC_PS_DISPLAYASICON, ps_struct->flags & PSF_CHECKDISPLAYASICON);
386 EnableWindow(display_as_icon, 0);
387 ShowWindow(icon_display, SW_HIDE);
388 EnableWindow(icon_display, 0);
389 ShowWindow(change_icon, SW_HIDE);
390 EnableWindow(change_icon, 0);
393 static void update_result_text(HWND hdlg, const ps_struct_t *ps_struct)
395 WCHAR resource_txt[200];
396 UINT res_id;
397 OLEUIPASTEENTRYW *pent;
398 LONG cur_sel;
399 static const WCHAR percent_s[] = {'%','s',0};
400 WCHAR *result_txt, *ptr;
402 cur_sel = SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETCURSEL, 0, 0);
403 if(cur_sel == -1) return;
404 pent = (OLEUIPASTEENTRYW*)SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETITEMDATA, cur_sel, 0);
406 if(ps_struct->flags & PSF_SELECTPASTE)
408 if(ps_struct->flags & PSF_CHECKDISPLAYASICON)
409 res_id = IDS_PS_PASTE_OBJECT_AS_ICON;
410 else
411 res_id = IDS_PS_PASTE_DATA;
413 else
415 if(ps_struct->flags & PSF_CHECKDISPLAYASICON)
416 res_id = IDS_PS_PASTE_LINK_OBJECT_AS_ICON;
417 else
418 res_id = IDS_PS_PASTE_LINK_DATA;
421 LoadStringW(OLEDLG_hInstance, res_id, resource_txt, ARRAY_SIZE(resource_txt));
422 if((ptr = wcsstr(resource_txt, percent_s)))
424 /* FIXME handle %s in ResultText. Sub appname if IDS_PS_PASTE_OBJECT{_AS_ICON}. Else sub appropriate type name */
425 size_t result_txt_len = lstrlenW(pent->lpstrResultText);
426 ptrdiff_t offs = (char*)ptr - (char*)resource_txt;
427 result_txt = malloc((wcslen(resource_txt) + result_txt_len - 1) * sizeof(WCHAR));
428 memcpy(result_txt, resource_txt, offs);
429 memcpy((char*)result_txt + offs, pent->lpstrResultText, result_txt_len * sizeof(WCHAR));
430 memcpy((char*)result_txt + offs + result_txt_len * sizeof(WCHAR), ptr + 2, (lstrlenW(ptr + 2) + 1) * sizeof(WCHAR));
432 else
433 result_txt = resource_txt;
435 SetDlgItemTextW(hdlg, IDC_PS_RESULTTEXT, result_txt);
437 if(result_txt != resource_txt)
438 free(result_txt);
442 static void selection_change(HWND hdlg, ps_struct_t *ps_struct)
444 update_as_icon(hdlg, ps_struct);
445 update_result_text(hdlg, ps_struct);
448 static void mode_change(HWND hdlg, ps_struct_t *ps_struct, UINT id)
450 if(id == IDC_PS_PASTE)
452 ps_struct->flags &= ~PSF_SELECTPASTELINK;
453 ps_struct->flags |= PSF_SELECTPASTE;
455 else
457 ps_struct->flags &= ~PSF_SELECTPASTE;
458 ps_struct->flags |= PSF_SELECTPASTELINK;
461 update_src_text(hdlg, ps_struct);
462 update_display_list(hdlg, id == IDC_PS_PASTE ? IDC_PS_PASTELIST : IDC_PS_PASTELINKLIST);
463 selection_change(hdlg, ps_struct);
466 static void post_help_msg(HWND hdlg, ps_struct_t *ps_struct)
468 PostMessageW(ps_struct->ps->hWndOwner, oleui_msg_help, (WPARAM)hdlg, IDD_PASTESPECIAL);
471 static void send_end_dialog_msg(HWND hdlg, ps_struct_t *ps_struct, UINT id)
473 SendMessageW(hdlg, oleui_msg_enddialog, id, 0);
476 static void update_structure(HWND hdlg, ps_struct_t *ps_struct)
478 LONG cur_sel = SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETCURSEL, 0, 0);
479 if(cur_sel != -1)
481 OLEUIPASTEENTRYW *pent;
482 pent = (OLEUIPASTEENTRYW *)SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETITEMDATA, cur_sel, 0);
483 ps_struct->ps->nSelectedIndex = pent->dwScratchSpace;
485 ps_struct->ps->dwFlags = ps_struct->flags;
486 ps_struct->ps->fLink = (ps_struct->flags & PSF_SELECTPASTELINK) != 0;
489 static void free_structure(ps_struct_t *ps_struct)
491 free(ps_struct->type_name);
492 free(ps_struct->source_name);
493 free(ps_struct->link_type_name);
494 free(ps_struct->link_source_name);
495 CoTaskMemFree(ps_struct->app_name);
496 free(ps_struct);
499 static INT_PTR CALLBACK ps_dlg_proc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp)
501 /* native uses prop name "Structure", but we're not compatible
502 with that so we'll prepend "Wine_". */
503 static const WCHAR prop_name[] = {'W','i','n','e','_','S','t','r','u','c','t','u','r','e',0};
504 ps_struct_t *ps_struct;
506 TRACE("(%p, %04x, %08Ix, %08Ix)\n", hdlg, msg, wp, lp);
508 ps_struct = GetPropW(hdlg, prop_name);
510 if(msg != WM_INITDIALOG)
512 if(!ps_struct)
513 return 0;
515 if(ps_struct->ps->lpfnHook)
517 INT_PTR ret = ps_struct->ps->lpfnHook(hdlg, msg, wp, lp);
518 if(ret) return ret;
522 switch(msg)
524 case WM_INITDIALOG:
526 ps_struct = malloc(sizeof(*ps_struct));
527 ps_struct->ps = (OLEUIPASTESPECIALW*)lp;
528 ps_struct->type_name = NULL;
529 ps_struct->source_name = NULL;
530 ps_struct->link_type_name = NULL;
531 ps_struct->link_source_name = NULL;
532 ps_struct->app_name = NULL;
533 ps_struct->flags = ps_struct->ps->dwFlags;
535 SetPropW(hdlg, prop_name, ps_struct);
537 if(!(ps_struct->ps->dwFlags & PSF_SHOWHELP))
539 ShowWindow(GetDlgItem(hdlg, IDC_OLEUIHELP), SW_HIDE);
540 EnableWindow(GetDlgItem(hdlg, IDC_OLEUIHELP), 0);
543 if(ps_struct->ps->lpszCaption)
544 SetWindowTextW(hdlg, ps_struct->ps->lpszCaption);
546 get_descriptors(hdlg, ps_struct);
548 init_lists(hdlg, ps_struct);
550 update_src_text(hdlg, ps_struct);
552 selection_change(hdlg, ps_struct);
554 SetFocus(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST));
556 if(ps_struct->ps->lpfnHook)
557 ps_struct->ps->lpfnHook(hdlg, msg, 0, 0);
558 return FALSE; /* use new focus */
560 case WM_COMMAND:
561 switch(LOWORD(wp))
563 case IDC_PS_DISPLAYLIST:
564 switch(HIWORD(wp))
566 case LBN_SELCHANGE:
567 selection_change(hdlg, ps_struct);
568 return FALSE;
569 default:
570 return FALSE;
572 case IDC_PS_PASTE:
573 case IDC_PS_PASTELINK:
574 switch(HIWORD(wp))
576 case BN_CLICKED:
577 mode_change(hdlg, ps_struct, LOWORD(wp));
578 return FALSE;
580 default:
581 return FALSE;
583 case IDC_OLEUIHELP:
584 switch(HIWORD(wp))
586 case BN_CLICKED:
587 post_help_msg(hdlg, ps_struct);
588 return FALSE;
589 default:
590 return FALSE;
592 case IDOK:
593 case IDCANCEL:
594 switch(HIWORD(wp))
596 case BN_CLICKED:
597 send_end_dialog_msg(hdlg, ps_struct, LOWORD(wp));
598 return FALSE;
599 default:
600 return FALSE;
603 return FALSE;
604 default:
605 if(msg == oleui_msg_enddialog)
607 if(wp == IDOK)
608 update_structure(hdlg, ps_struct);
609 EndDialog(hdlg, wp);
610 /* native does its cleanup in WM_DESTROY */
611 RemovePropW(hdlg, prop_name);
612 free_structure(ps_struct);
613 return TRUE;
615 return FALSE;
620 /***********************************************************************
621 * OleUIPasteSpecialA (OLEDLG.4)
623 UINT WINAPI OleUIPasteSpecialA(LPOLEUIPASTESPECIALA psA)
625 OLEUIPASTESPECIALW ps;
626 UINT ret;
627 TRACE("(%p)\n", psA);
629 memcpy(&ps, psA, psA->cbStruct);
631 ps.lpszCaption = strdupAtoW(psA->lpszCaption);
632 if(!IS_INTRESOURCE(ps.lpszTemplate))
633 ps.lpszTemplate = strdupAtoW(psA->lpszTemplate);
635 if(psA->cPasteEntries > 0)
637 DWORD size = psA->cPasteEntries * sizeof(ps.arrPasteEntries[0]);
638 INT i;
640 ps.arrPasteEntries = malloc(size);
641 memcpy(ps.arrPasteEntries, psA->arrPasteEntries, size);
642 for(i = 0; i < psA->cPasteEntries; i++)
644 ps.arrPasteEntries[i].lpstrFormatName =
645 strdupAtoW(psA->arrPasteEntries[i].lpstrFormatName);
646 ps.arrPasteEntries[i].lpstrResultText =
647 strdupAtoW(psA->arrPasteEntries[i].lpstrResultText);
651 ret = OleUIPasteSpecialW(&ps);
653 if(psA->cPasteEntries > 0)
655 INT i;
656 for(i = 0; i < psA->cPasteEntries; i++)
658 free((WCHAR*)ps.arrPasteEntries[i].lpstrFormatName);
659 free((WCHAR*)ps.arrPasteEntries[i].lpstrResultText);
661 free(ps.arrPasteEntries);
663 if(!IS_INTRESOURCE(ps.lpszTemplate))
664 free((WCHAR*)ps.lpszTemplate);
665 free((WCHAR*)ps.lpszCaption);
667 /* Copy back the output fields */
668 psA->dwFlags = ps.dwFlags;
669 psA->lpSrcDataObj = ps.lpSrcDataObj;
670 psA->nSelectedIndex = ps.nSelectedIndex;
671 psA->fLink = ps.fLink;
672 psA->hMetaPict = ps.hMetaPict;
673 psA->sizel = ps.sizel;
675 return ret;
678 /***********************************************************************
679 * OleUIPasteSpecialW (OLEDLG.22)
681 UINT WINAPI OleUIPasteSpecialW(LPOLEUIPASTESPECIALW ps)
683 LPCDLGTEMPLATEW dlg_templ = (LPCDLGTEMPLATEW)ps->hResource;
684 UINT ret;
686 TRACE("(%p)\n", ps);
688 if(TRACE_ON(ole)) dump_pastespecial(ps);
690 if(!ps->lpSrcDataObj)
691 OleGetClipboard(&ps->lpSrcDataObj);
693 if(ps->hInstance || !ps->hResource)
695 HINSTANCE hInst = ps->hInstance ? ps->hInstance : OLEDLG_hInstance;
696 const WCHAR *name = ps->hInstance ? ps->lpszTemplate : MAKEINTRESOURCEW(IDD_PASTESPECIAL4);
697 HRSRC hrsrc;
699 if(name == NULL) return OLEUI_ERR_LPSZTEMPLATEINVALID;
700 hrsrc = FindResourceW(hInst, name, (LPWSTR)RT_DIALOG);
701 if(!hrsrc) return OLEUI_ERR_FINDTEMPLATEFAILURE;
702 dlg_templ = LoadResource(hInst, hrsrc);
703 if(!dlg_templ) return OLEUI_ERR_LOADTEMPLATEFAILURE;
706 ret = DialogBoxIndirectParamW(OLEDLG_hInstance, dlg_templ, ps->hWndOwner, ps_dlg_proc, (LPARAM)ps);
708 return ret;