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 WIN32_NO_STATUS
23 #define COM_NO_WINDOWS_H
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
33 //#include "winerror.h"
39 #include "oledlg_private.h"
42 #include <wine/debug.h>
43 #include <wine/unicode.h>
45 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
49 OLEUIPASTESPECIALW
*ps
;
52 WCHAR
*link_source_name
;
54 WCHAR
*link_type_name
;
58 static const struct ps_flag
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
),
76 static void dump_ps_flags(DWORD flags
)
78 char flagstr
[1000] = "";
80 const struct ps_flag
*flag
= ps_flags
;
81 for( ; flag
->name
; flag
++) {
82 if(flags
& flag
->flag
) {
83 strcat(flagstr
, flag
->name
);
87 TRACE("flags %08x %s\n", flags
, flagstr
);
90 static void dump_pastespecial(const OLEUIPASTESPECIALW
*ps
)
93 dump_ps_flags(ps
->dwFlags
);
94 TRACE("hwnd %p caption %s hook %p custdata %lx\n",
95 ps
->hWndOwner
, debugstr_w(ps
->lpszCaption
), ps
->lpfnHook
, ps
->lCustData
);
96 if(IS_INTRESOURCE(ps
->lpszTemplate
))
97 TRACE("hinst %p template %04x hresource %p\n", ps
->hInstance
, (WORD
)(ULONG_PTR
)ps
->lpszTemplate
, ps
->hResource
);
99 TRACE("hinst %p template %s hresource %p\n", ps
->hInstance
, debugstr_w(ps
->lpszTemplate
), ps
->hResource
);
100 TRACE("dataobj %p arrpasteent %p cpasteent %d arrlinktype %p clinktype %d\n",
101 ps
->lpSrcDataObj
, ps
->arrPasteEntries
, ps
->cPasteEntries
,
102 ps
->arrLinkTypes
, ps
->cLinkTypes
);
103 TRACE("cclsidex %d lpclsidex %p nselect %d flink %d hmetapict %p size(%d,%d)\n",
104 ps
->cClsidExclude
, ps
->lpClsidExclude
, ps
->nSelectedIndex
, ps
->fLink
,
105 ps
->hMetaPict
, ps
->sizel
.cx
, ps
->sizel
.cy
);
106 for(i
= 0; i
< ps
->cPasteEntries
; i
++)
108 TRACE("arrPasteEntries[%d]: cFormat %08x pTargetDevice %p dwAspect %d lindex %d tymed %d\n",
109 i
, ps
->arrPasteEntries
[i
].fmtetc
.cfFormat
, ps
->arrPasteEntries
[i
].fmtetc
.ptd
,
110 ps
->arrPasteEntries
[i
].fmtetc
.dwAspect
, ps
->arrPasteEntries
[i
].fmtetc
.lindex
,
111 ps
->arrPasteEntries
[i
].fmtetc
.tymed
);
112 TRACE("\tformat name %s result text %s flags %04x\n", debugstr_w(ps
->arrPasteEntries
[i
].lpstrFormatName
),
113 debugstr_w(ps
->arrPasteEntries
[i
].lpstrResultText
), ps
->arrPasteEntries
[i
].dwFlags
);
115 for(i
= 0; i
< ps
->cLinkTypes
; i
++)
116 TRACE("arrLinkTypes[%d] %08x\n", i
, ps
->arrLinkTypes
[i
]);
117 for(i
= 0; i
< ps
->cClsidExclude
; i
++)
118 TRACE("lpClsidExclude[%d] %s\n", i
, debugstr_guid(&ps
->lpClsidExclude
[i
]));
122 static inline WCHAR
*strdupAtoW(const char *str
)
126 if(!str
) return NULL
;
127 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
128 ret
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
129 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
133 static inline WCHAR
*strdupW(const WCHAR
*str
)
137 if(!str
) return NULL
;
138 len
= lstrlenW(str
) + 1;
139 ret
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
140 memcpy(ret
, str
, len
* sizeof(WCHAR
));
144 static void get_descriptors(HWND hdlg
, ps_struct_t
*ps_struct
)
149 fmtetc
.tymed
= TYMED_HGLOBAL
;
150 fmtetc
.dwAspect
= DVASPECT_CONTENT
;
154 fmtetc
.cfFormat
= cf_object_descriptor
;
155 if(IDataObject_GetData(ps_struct
->ps
->lpSrcDataObj
, &fmtetc
, &stg
) == S_OK
)
157 OBJECTDESCRIPTOR
*obj_desc
= GlobalLock(stg
.u
.hGlobal
);
158 if(obj_desc
->dwSrcOfCopy
)
159 ps_struct
->source_name
= strdupW((WCHAR
*)((char*)obj_desc
+ obj_desc
->dwSrcOfCopy
));
160 if(obj_desc
->dwFullUserTypeName
)
161 ps_struct
->type_name
= strdupW((WCHAR
*)((char*)obj_desc
+ obj_desc
->dwFullUserTypeName
));
162 OleRegGetUserType(&obj_desc
->clsid
, USERCLASSTYPE_APPNAME
, &ps_struct
->app_name
);
163 /* Get the icon here. If dwDrawAspect & DVASCPECT_ICON call GetData(CF_METAFILEPICT), otherwise
164 native calls OleGetIconFromClass(obj_desc->clsid) */
165 GlobalUnlock(stg
.u
.hGlobal
);
166 GlobalFree(stg
.u
.hGlobal
);
170 /* Try to get some data using some of the other clipboard formats */
173 fmtetc
.cfFormat
= cf_link_src_descriptor
;
174 if(IDataObject_GetData(ps_struct
->ps
->lpSrcDataObj
, &fmtetc
, &stg
) == S_OK
)
176 OBJECTDESCRIPTOR
*obj_desc
= GlobalLock(stg
.u
.hGlobal
);
177 if(obj_desc
->dwSrcOfCopy
)
178 ps_struct
->link_source_name
= strdupW((WCHAR
*)((char*)obj_desc
+ obj_desc
->dwSrcOfCopy
));
179 if(obj_desc
->dwFullUserTypeName
)
180 ps_struct
->link_type_name
= strdupW((WCHAR
*)((char*)obj_desc
+ obj_desc
->dwFullUserTypeName
));
181 GlobalUnlock(stg
.u
.hGlobal
);
182 GlobalFree(stg
.u
.hGlobal
);
185 if(ps_struct
->source_name
== NULL
&& ps_struct
->link_source_name
== NULL
)
188 LoadStringW(OLEDLG_hInstance
, IDS_PS_UNKNOWN_SRC
, buf
, sizeof(buf
)/sizeof(WCHAR
));
189 ps_struct
->source_name
= strdupW(buf
);
192 if(ps_struct
->type_name
== NULL
&& ps_struct
->link_type_name
== NULL
)
195 LoadStringW(OLEDLG_hInstance
, IDS_PS_UNKNOWN_TYPE
, buf
, sizeof(buf
)/sizeof(WCHAR
));
196 ps_struct
->type_name
= strdupW(buf
);
200 static BOOL
add_entry_to_lb(HWND hdlg
, UINT id
, OLEUIPASTEENTRYW
*pe
)
202 HWND hwnd
= GetDlgItem(hdlg
, id
);
205 /* FIXME %s handling */
207 /* Note that this suffers from the same bug as native, in that if a new string
208 is a substring of an already added string, then the FINDSTRING will succeed
209 this is probably not what we want */
210 if(SendMessageW(hwnd
, LB_FINDSTRING
, 0, (LPARAM
)pe
->lpstrFormatName
) == -1)
212 LRESULT pos
= SendMessageW(hwnd
, LB_ADDSTRING
, 0, (LPARAM
)pe
->lpstrFormatName
);
213 SendMessageW(hwnd
, LB_SETITEMDATA
, pos
, (LPARAM
)pe
);
219 static DWORD
init_pastelist(HWND hdlg
, OLEUIPASTESPECIALW
*ps
)
221 IEnumFORMATETC
*penum
;
224 DWORD fetched
, items_added
= 0;
226 hr
= IDataObject_EnumFormatEtc(ps
->lpSrcDataObj
, DATADIR_GET
, &penum
);
229 WARN("Unable to create IEnumFORMATETC\n");
233 /* The native version grabs only the first 20 fmts and we do the same */
234 hr
= IEnumFORMATETC_Next(penum
, sizeof(fmts
)/sizeof(fmts
[0]), fmts
, &fetched
);
235 TRACE("got %d formats hr %08x\n", fetched
, hr
);
239 DWORD src_fmt
, req_fmt
;
240 for(req_fmt
= 0; req_fmt
< ps
->cPasteEntries
; req_fmt
++)
242 /* This is used by update_structure() to set nSelectedIndex on exit */
243 ps
->arrPasteEntries
[req_fmt
].dwScratchSpace
= req_fmt
;
244 TRACE("req_fmt %x\n", ps
->arrPasteEntries
[req_fmt
].fmtetc
.cfFormat
);
245 for(src_fmt
= 0; src_fmt
< fetched
; src_fmt
++)
247 TRACE("\tenum'ed fmt %x\n", fmts
[src_fmt
].cfFormat
);
248 if(ps
->arrPasteEntries
[req_fmt
].fmtetc
.cfFormat
== fmts
[src_fmt
].cfFormat
)
250 add_entry_to_lb(hdlg
, IDC_PS_PASTELIST
, ps
->arrPasteEntries
+ req_fmt
);
258 IEnumFORMATETC_Release(penum
);
259 EnableWindow(GetDlgItem(hdlg
, IDC_PS_PASTE
), items_added
? TRUE
: FALSE
);
263 static DWORD
init_linklist(HWND hdlg
, OLEUIPASTESPECIALW
*ps
)
266 DWORD supported_mask
= 0;
267 DWORD items_added
= 0;
269 FORMATETC fmt
= {0, NULL
, DVASPECT_CONTENT
, -1, -1};
271 for(link
= 0; link
< ps
->cLinkTypes
&& link
< PS_MAXLINKTYPES
; link
++)
273 fmt
.cfFormat
= ps
->arrLinkTypes
[link
];
274 hr
= IDataObject_QueryGetData(ps
->lpSrcDataObj
, &fmt
);
276 supported_mask
|= 1 << link
;
278 TRACE("supported_mask %02x\n", supported_mask
);
279 for(req_fmt
= 0; req_fmt
< ps
->cPasteEntries
; req_fmt
++)
282 if(ps
->arrPasteEntries
[req_fmt
].dwFlags
& OLEUIPASTE_LINKANYTYPE
)
285 linktypes
= ps
->arrPasteEntries
[req_fmt
].dwFlags
& 0xff;
287 if(linktypes
& supported_mask
)
289 add_entry_to_lb(hdlg
, IDC_PS_PASTELINKLIST
, ps
->arrPasteEntries
+ req_fmt
);
294 EnableWindow(GetDlgItem(hdlg
, IDC_PS_PASTELINK
), items_added
? TRUE
: FALSE
);
298 /* copies src_list_id into the display list */
299 static void update_display_list(HWND hdlg
, UINT src_list_id
)
301 LONG count
, i
, old_pos
;
304 HWND display_list
= GetDlgItem(hdlg
, IDC_PS_DISPLAYLIST
);
305 HWND list
= GetDlgItem(hdlg
, src_list_id
);
307 old_pos
= SendMessageW(display_list
, LB_GETCURSEL
, 0, 0);
308 if(old_pos
== -1) old_pos
= 0;
310 SendMessageW(display_list
, WM_SETREDRAW
, 0, 0);
311 SendMessageW(display_list
, LB_RESETCONTENT
, 0, 0);
312 count
= SendMessageW(list
, LB_GETCOUNT
, 0, 0);
313 for(i
= 0; i
< count
; i
++)
315 SendMessageW(list
, LB_GETTEXT
, i
, (LPARAM
)txt
);
316 item_data
= SendMessageW(list
, LB_GETITEMDATA
, i
, 0);
317 SendMessageW(display_list
, LB_INSERTSTRING
, i
, (LPARAM
)txt
);
318 SendMessageW(display_list
, LB_SETITEMDATA
, i
, item_data
);
320 old_pos
= max(old_pos
, count
);
321 SendMessageW(display_list
, LB_SETCURSEL
, 0, 0);
322 SendMessageW(display_list
, WM_SETREDRAW
, 1, 0);
323 if(GetForegroundWindow() == hdlg
)
324 SetFocus(display_list
);
327 static void init_lists(HWND hdlg
, ps_struct_t
*ps_struct
)
329 DWORD pastes_added
= init_pastelist(hdlg
, ps_struct
->ps
);
330 DWORD links_added
= init_linklist(hdlg
, ps_struct
->ps
);
331 UINT check_id
, list_id
;
333 if((ps_struct
->flags
& (PSF_SELECTPASTE
| PSF_SELECTPASTELINK
)) == 0)
334 ps_struct
->flags
|= PSF_SELECTPASTE
;
336 if(!pastes_added
&& !links_added
)
337 ps_struct
->flags
&= ~(PSF_SELECTPASTE
| PSF_SELECTPASTELINK
);
338 else if(!pastes_added
&& (ps_struct
->flags
& PSF_SELECTPASTE
))
340 ps_struct
->flags
&= ~PSF_SELECTPASTE
;
341 ps_struct
->flags
|= PSF_SELECTPASTELINK
;
343 else if(!links_added
&& (ps_struct
->flags
& PSF_SELECTPASTELINK
))
345 ps_struct
->flags
&= ~PSF_SELECTPASTELINK
;
346 ps_struct
->flags
|= PSF_SELECTPASTE
;
351 if(ps_struct
->flags
& PSF_SELECTPASTE
)
353 check_id
= IDC_PS_PASTE
;
354 list_id
= IDC_PS_PASTELIST
;
356 else if(ps_struct
->flags
& PSF_SELECTPASTELINK
)
358 check_id
= IDC_PS_PASTELINK
;
359 list_id
= IDC_PS_PASTELINKLIST
;
362 CheckRadioButton(hdlg
, IDC_PS_PASTE
, IDC_PS_PASTELINK
, check_id
);
365 update_display_list(hdlg
, list_id
);
367 EnableWindow(GetDlgItem(hdlg
, IDOK
), 0);
370 static void update_src_text(HWND hdlg
, const ps_struct_t
*ps_struct
)
374 if(ps_struct
->flags
& PSF_SELECTPASTE
)
376 if(ps_struct
->source_name
)
377 str
= ps_struct
->source_name
;
379 str
= ps_struct
->link_source_name
;
384 if(ps_struct
->link_source_name
)
385 str
= ps_struct
->link_source_name
;
387 str
= ps_struct
->source_name
;
390 SetDlgItemTextW(hdlg
, IDC_PS_SOURCETEXT
, str
);
393 static void update_as_icon(HWND hdlg
, ps_struct_t
*ps_struct
)
395 HWND icon_display
= GetDlgItem(hdlg
, IDC_PS_ICONDISPLAY
);
396 HWND display_as_icon
= GetDlgItem(hdlg
, IDC_PS_DISPLAYASICON
);
397 HWND change_icon
= GetDlgItem(hdlg
, IDC_PS_CHANGEICON
);
399 /* FIXME. No as icon handling */
400 ps_struct
->flags
&= ~PSF_CHECKDISPLAYASICON
;
402 CheckDlgButton(hdlg
, IDC_PS_DISPLAYASICON
, ps_struct
->flags
& PSF_CHECKDISPLAYASICON
);
403 EnableWindow(display_as_icon
, 0);
404 ShowWindow(icon_display
, SW_HIDE
);
405 EnableWindow(icon_display
, 0);
406 ShowWindow(change_icon
, SW_HIDE
);
407 EnableWindow(change_icon
, 0);
410 static void update_result_text(HWND hdlg
, const ps_struct_t
*ps_struct
)
412 WCHAR resource_txt
[200];
414 OLEUIPASTEENTRYW
*pent
;
416 static const WCHAR percent_s
[] = {'%','s',0};
417 WCHAR
*result_txt
, *ptr
;
419 cur_sel
= SendMessageW(GetDlgItem(hdlg
, IDC_PS_DISPLAYLIST
), LB_GETCURSEL
, 0, 0);
420 if(cur_sel
== -1) return;
421 pent
= (OLEUIPASTEENTRYW
*)SendMessageW(GetDlgItem(hdlg
, IDC_PS_DISPLAYLIST
), LB_GETITEMDATA
, cur_sel
, 0);
423 if(ps_struct
->flags
& PSF_SELECTPASTE
)
425 if(ps_struct
->flags
& PSF_CHECKDISPLAYASICON
)
426 res_id
= IDS_PS_PASTE_OBJECT_AS_ICON
;
428 res_id
= IDS_PS_PASTE_DATA
;
432 if(ps_struct
->flags
& PSF_CHECKDISPLAYASICON
)
433 res_id
= IDS_PS_PASTE_LINK_OBJECT_AS_ICON
;
435 res_id
= IDS_PS_PASTE_LINK_DATA
;
438 LoadStringW(OLEDLG_hInstance
, res_id
, resource_txt
, sizeof(resource_txt
)/sizeof(WCHAR
));
439 if((ptr
= strstrW(resource_txt
, percent_s
)))
441 /* FIXME handle %s in ResultText. Sub appname if IDS_PS_PASTE_OBJECT{_AS_ICON}. Else sub appropriate type name */
442 size_t result_txt_len
= strlenW(pent
->lpstrResultText
);
443 ptrdiff_t offs
= (char*)ptr
- (char*)resource_txt
;
444 result_txt
= HeapAlloc(GetProcessHeap(), 0, (strlenW(resource_txt
) + result_txt_len
- 1) * sizeof(WCHAR
));
445 memcpy(result_txt
, resource_txt
, offs
);
446 memcpy((char*)result_txt
+ offs
, pent
->lpstrResultText
, result_txt_len
* sizeof(WCHAR
));
447 memcpy((char*)result_txt
+ offs
+ result_txt_len
* sizeof(WCHAR
), ptr
+ 2, (strlenW(ptr
+ 2) + 1) * sizeof(WCHAR
));
450 result_txt
= resource_txt
;
452 SetDlgItemTextW(hdlg
, IDC_PS_RESULTTEXT
, result_txt
);
454 if(result_txt
!= resource_txt
)
455 HeapFree(GetProcessHeap(), 0, result_txt
);
459 static void selection_change(HWND hdlg
, ps_struct_t
*ps_struct
)
461 update_as_icon(hdlg
, ps_struct
);
462 update_result_text(hdlg
, ps_struct
);
465 static void mode_change(HWND hdlg
, ps_struct_t
*ps_struct
, UINT id
)
467 if(id
== IDC_PS_PASTE
)
469 ps_struct
->flags
&= ~PSF_SELECTPASTELINK
;
470 ps_struct
->flags
|= PSF_SELECTPASTE
;
474 ps_struct
->flags
&= ~PSF_SELECTPASTE
;
475 ps_struct
->flags
|= PSF_SELECTPASTELINK
;
478 update_src_text(hdlg
, ps_struct
);
479 update_display_list(hdlg
, id
== IDC_PS_PASTE
? IDC_PS_PASTELIST
: IDC_PS_PASTELINKLIST
);
480 selection_change(hdlg
, ps_struct
);
483 static void post_help_msg(HWND hdlg
, ps_struct_t
*ps_struct
)
485 PostMessageW(ps_struct
->ps
->hWndOwner
, oleui_msg_help
, (WPARAM
)hdlg
, IDD_PASTESPECIAL
);
488 static void send_end_dialog_msg(HWND hdlg
, ps_struct_t
*ps_struct
, UINT id
)
490 SendMessageW(hdlg
, oleui_msg_enddialog
, id
, 0);
493 static void update_structure(HWND hdlg
, ps_struct_t
*ps_struct
)
495 LONG cur_sel
= SendMessageW(GetDlgItem(hdlg
, IDC_PS_DISPLAYLIST
), LB_GETCURSEL
, 0, 0);
498 OLEUIPASTEENTRYW
*pent
;
499 pent
= (OLEUIPASTEENTRYW
*)SendMessageW(GetDlgItem(hdlg
, IDC_PS_DISPLAYLIST
), LB_GETITEMDATA
, cur_sel
, 0);
500 ps_struct
->ps
->nSelectedIndex
= pent
->dwScratchSpace
;
502 ps_struct
->ps
->dwFlags
= ps_struct
->flags
;
503 ps_struct
->ps
->fLink
= (ps_struct
->flags
& PSF_SELECTPASTELINK
) ? TRUE
: FALSE
;
506 static void free_structure(ps_struct_t
*ps_struct
)
508 HeapFree(GetProcessHeap(), 0, ps_struct
->type_name
);
509 HeapFree(GetProcessHeap(), 0, ps_struct
->source_name
);
510 HeapFree(GetProcessHeap(), 0, ps_struct
->link_type_name
);
511 HeapFree(GetProcessHeap(), 0, ps_struct
->link_source_name
);
512 CoTaskMemFree(ps_struct
->app_name
);
513 HeapFree(GetProcessHeap(), 0, ps_struct
);
516 static INT_PTR CALLBACK
ps_dlg_proc(HWND hdlg
, UINT msg
, WPARAM wp
, LPARAM lp
)
518 /* native uses prop name "Structure", but we're not compatible
519 with that so we'll prepend "Wine_". */
520 static const WCHAR prop_name
[] = {'W','i','n','e','_','S','t','r','u','c','t','u','r','e',0};
521 ps_struct_t
*ps_struct
;
523 TRACE("(%p, %04x, %08lx, %08lx)\n", hdlg
, msg
, wp
, lp
);
525 ps_struct
= GetPropW(hdlg
, prop_name
);
527 if(msg
!= WM_INITDIALOG
)
532 if(ps_struct
->ps
->lpfnHook
)
534 INT_PTR ret
= ps_struct
->ps
->lpfnHook(hdlg
, msg
, wp
, lp
);
543 ps_struct
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ps_struct
));
544 ps_struct
->ps
= (OLEUIPASTESPECIALW
*)lp
;
545 ps_struct
->type_name
= NULL
;
546 ps_struct
->source_name
= NULL
;
547 ps_struct
->link_type_name
= NULL
;
548 ps_struct
->link_source_name
= NULL
;
549 ps_struct
->app_name
= NULL
;
550 ps_struct
->flags
= ps_struct
->ps
->dwFlags
;
552 SetPropW(hdlg
, prop_name
, ps_struct
);
554 if(!(ps_struct
->ps
->dwFlags
& PSF_SHOWHELP
))
556 ShowWindow(GetDlgItem(hdlg
, IDC_OLEUIHELP
), SW_HIDE
);
557 EnableWindow(GetDlgItem(hdlg
, IDC_OLEUIHELP
), 0);
560 if(ps_struct
->ps
->lpszCaption
)
561 SetWindowTextW(hdlg
, ps_struct
->ps
->lpszCaption
);
563 get_descriptors(hdlg
, ps_struct
);
565 init_lists(hdlg
, ps_struct
);
567 update_src_text(hdlg
, ps_struct
);
569 selection_change(hdlg
, ps_struct
);
571 SetFocus(GetDlgItem(hdlg
, IDC_PS_DISPLAYLIST
));
573 if(ps_struct
->ps
->lpfnHook
)
574 ps_struct
->ps
->lpfnHook(hdlg
, msg
, 0, 0);
575 return FALSE
; /* use new focus */
580 case IDC_PS_DISPLAYLIST
:
584 selection_change(hdlg
, ps_struct
);
590 case IDC_PS_PASTELINK
:
594 mode_change(hdlg
, ps_struct
, LOWORD(wp
));
604 post_help_msg(hdlg
, ps_struct
);
614 send_end_dialog_msg(hdlg
, ps_struct
, LOWORD(wp
));
622 if(msg
== oleui_msg_enddialog
)
625 update_structure(hdlg
, ps_struct
);
627 /* native does its cleanup in WM_DESTROY */
628 RemovePropW(hdlg
, prop_name
);
629 free_structure(ps_struct
);
637 /***********************************************************************
638 * OleUIPasteSpecialA (OLEDLG.4)
640 UINT WINAPI
OleUIPasteSpecialA(LPOLEUIPASTESPECIALA psA
)
642 OLEUIPASTESPECIALW ps
;
644 TRACE("(%p)\n", psA
);
646 memcpy(&ps
, psA
, psA
->cbStruct
);
648 ps
.lpszCaption
= strdupAtoW(psA
->lpszCaption
);
649 if(!IS_INTRESOURCE(ps
.lpszTemplate
))
650 ps
.lpszTemplate
= strdupAtoW(psA
->lpszTemplate
);
652 if(psA
->cPasteEntries
> 0)
654 DWORD size
= psA
->cPasteEntries
* sizeof(ps
.arrPasteEntries
[0]);
657 ps
.arrPasteEntries
= HeapAlloc(GetProcessHeap(), 0, size
);
658 memcpy(ps
.arrPasteEntries
, psA
->arrPasteEntries
, size
);
659 for(i
= 0; i
< psA
->cPasteEntries
; i
++)
661 ps
.arrPasteEntries
[i
].lpstrFormatName
=
662 strdupAtoW(psA
->arrPasteEntries
[i
].lpstrFormatName
);
663 ps
.arrPasteEntries
[i
].lpstrResultText
=
664 strdupAtoW(psA
->arrPasteEntries
[i
].lpstrResultText
);
668 ret
= OleUIPasteSpecialW(&ps
);
670 if(psA
->cPasteEntries
> 0)
673 for(i
= 0; i
< psA
->cPasteEntries
; i
++)
675 HeapFree(GetProcessHeap(), 0, (WCHAR
*)ps
.arrPasteEntries
[i
].lpstrFormatName
);
676 HeapFree(GetProcessHeap(), 0, (WCHAR
*)ps
.arrPasteEntries
[i
].lpstrResultText
);
678 HeapFree(GetProcessHeap(), 0, ps
.arrPasteEntries
);
680 if(!IS_INTRESOURCE(ps
.lpszTemplate
))
681 HeapFree(GetProcessHeap(), 0, (WCHAR
*)ps
.lpszTemplate
);
682 HeapFree(GetProcessHeap(), 0, (WCHAR
*)ps
.lpszCaption
);
684 /* Copy back the output fields */
685 psA
->dwFlags
= ps
.dwFlags
;
686 psA
->lpSrcDataObj
= ps
.lpSrcDataObj
;
687 psA
->nSelectedIndex
= ps
.nSelectedIndex
;
688 psA
->fLink
= ps
.fLink
;
689 psA
->hMetaPict
= ps
.hMetaPict
;
690 psA
->sizel
= ps
.sizel
;
695 /***********************************************************************
696 * OleUIPasteSpecialW (OLEDLG.22)
698 UINT WINAPI
OleUIPasteSpecialW(LPOLEUIPASTESPECIALW ps
)
700 LPCDLGTEMPLATEW dlg_templ
= (LPCDLGTEMPLATEW
)ps
->hResource
;
705 if(TRACE_ON(ole
)) dump_pastespecial(ps
);
707 if(!ps
->lpSrcDataObj
)
708 OleGetClipboard(&ps
->lpSrcDataObj
);
710 if(ps
->hInstance
|| !ps
->hResource
)
712 HINSTANCE hInst
= ps
->hInstance
? ps
->hInstance
: OLEDLG_hInstance
;
713 const WCHAR
*name
= ps
->hInstance
? ps
->lpszTemplate
: MAKEINTRESOURCEW(IDD_PASTESPECIAL4
);
716 if(name
== NULL
) return OLEUI_ERR_LPSZTEMPLATEINVALID
;
717 hrsrc
= FindResourceW(hInst
, name
, MAKEINTRESOURCEW(RT_DIALOG
));
718 if(!hrsrc
) return OLEUI_ERR_FINDTEMPLATEFAILURE
;
719 dlg_templ
= LoadResource(hInst
, hrsrc
);
720 if(!dlg_templ
) return OLEUI_ERR_LOADTEMPLATEFAILURE
;
723 ret
= DialogBoxIndirectParamW(OLEDLG_hInstance
, dlg_templ
, ps
->hWndOwner
, ps_dlg_proc
, (LPARAM
)ps
);